The other axis

The term that came back

A phrase index is worth building because 8,192 characters parse into 156 phrases. Cap the copy depth at one and the same text parses into 7,351 — ninety per cent of the characters — and the structure is proportional to the text again.

Every compressed index in this field exists to remove one term. A suffix array is nlog2nn\lceil\log_2 n\rceil bits; an FM-index replaces that with something proportional to an entropy; a run-length index replaces the entropy with a run count; a phrase index replaces the run count with a phrase count. Each step is the same move, made against a smaller measure of the same text.

What is still proportional to n is the essay about what survives it. This one is about a constraint that undoes it.

What each cap costs in phrases, and what it holds the chain toA collection of 16 copies of 512 characters of English-like, parsed under each cap. The phrase count is 7,351 at a cap of one and 156 with no cap; the worst chain is 1 and 22. The two curves cross where the cap stops binding — at a cap of 8 the parse is within ten per cent of the unbounded one, and above that the cap is a declaration rather than a constraint. The left axis is phrases and the right is the chain, both linear.124816nonephrasescap on the copy chainphrasesworst chainEnglish-like · 8,192 charactersz 156 to 7,351
Fig. 1 The dial and its two ends: 156 phrases at a chain of 22, and 7,351 phrases at a chain of 1, on the same 8,192 characters.

The number

A collection of sixteen copies of five hundred and twelve characters of English-like text. 8,192 characters. Nineteen distinct symbols.

The greedy parse gives 156 phrases, which is 1.9% of the text. That is the whole case for the structure: an index with z in its size measures 8,892 bits for the index against 34,615 for a compressed FM-index over the same collection, and the reason is that 156 is a very small number.

The parse capped at depth one gives 7,351 phrases, which is 89.7% of the text. The index is 514,570 bits.

Sixty times the structure, and the text it is indexing has not changed by a character.

Why a cap of one is nearly a character-at-a-time enumeration

Because there is almost nowhere left to copy from.

A phrase at depth one must copy from a region at depth zero, and depth zero is the literals. A text over σ\sigma symbols has about σ\sigma literal phrases — one per symbol, after which every character has been seen — so a cap of one restricts every copy to a source region of a few dozen scattered characters.

Nineteen of them here, and they are single characters. A source region of one character supports a match of length one. So almost every phrase is a single character copied from the one literal of that symbol, and the parse is a character-at-a-time enumeration with a pointer instead of a letter.

That is worse than storing the text, and the arithmetic says by how much: 7,351 phrases at 2log2n+log2σ=26+5=312\lceil\log_2 n\rceil + \lceil\log_2\sigma\rceil = 26+5 = 31 bits each is 227,881 bits for the phrase table alone, against 8,192 characters at five bits, which is 40,960. A structure built to compress the text is twelve times the packed text.

The frontier a ceiling on the chain traces outEach point is one cap, on a collection of 16 copies of 512 characters of English-like. Left is a cheap character and up is a large structure, so the curve runs from the cap of one — depth 1 everywhere, 514,570 bits, a phrase count 47x the unbounded parse's — to no cap at all, at 8,580 bits and a worst chain of 22. Nothing on this curve dominates anything else on it, which is what makes it a frontier and not a ranking. Both axes are logarithmic.11010⁴10⁵worst copy chain, phrases followedbits124816noneno capcap on each pointEnglish-like · 16 copies of 512z 156 to 7,351
Fig. 2 The frontier, with the collapse at its left-hand end. The vertical run is where the constraint has stopped removing a tail and started charging for the bulk.

The measure was never the point on its own

The lesson is not “do not cap at one”. Nobody would. It is that a structure proportional to a measure of repetition is proportional to that measure under a specific set of allowances, and the allowances are part of the claim.

zz is small because the parse may copy from anywhere earlier, at any depth, with the source overlapping the phrase itself. Remove the depth allowance and zz is not small any more. The number 156 was never a property of the text alone; it was a property of the text and an unbounded chain, and the essay that introduced it said so in the sentence about what it was refusing to bound.

That is the same structure of claim a sampling that costs more than the array makes about the r-index’s run-boundary sampling: a structure built to remove a term proportional to the text costs, on four-symbol text, twice the whole suffix array it replaced. Both are cases where a measure’s smallness has a precondition and the precondition is where the interesting behaviour is.

What the intermediate settings do to the term

Between the two ends the phrase count is a fraction of the text: 89.7% at a cap of one, 34.9% at two, 11.5% at four, 2.08% at eight, 1.92% at sixteen, 1.90% uncapped.

So the term proportional to nn does not come back suddenly. It is present at every cap and it is negligible above about eight, on this collection — which is the same elbow the previous essay measures, seen through a different denominator.

What producing one character costs, against what the structure costs256 characters extracted from the middle of a collection of 8,192 characters, under each cap. The chain followed per character runs 1.00 at a cap of 1 to 10.00 with no cap, while the structure runs 514,570 bits down to 8,580. The measured cost per character is well under the cap at every point, because most positions are not on a long chain — the cap is a bound on the worst case and the mean is what a reader pays. Both axes are logarithmic.10,000100,000110bits heldphrases followed per charactercap 1cap 2cap 4cap 8cap noneEnglish-like · 256 characters extracted1.00 to 10.00 per character
Fig. 3 The two costs together. The left-hand end of this curve is where the structure has become larger than the text it replaces, in exchange for a character that costs exactly one phrase follow.

The right way to read that is as a statement about what the cap is for. A cap of eight on this collection is a bound on the read cost that costs nine per cent of the structure; a cap of one is a different kind of object entirely — a structure whose read cost is constant and whose size is linear in the text, which is to say an array of pointers, which is to say the text.

The thing that did not come back, which is the useful half

One quantity is unmoved by all of this and it is worth putting on the record, because it is what separates a bad structure from a structure at a bad setting.

The text is still recoverable and still not stored. At every cap, including one, the index holds no characters except the literals and produces the whole text from the parse. It is a self-index at 514,570 bits and it is a self-index at 8,580, and the seal that enforces that — every read of the text during a query is an error — is unchanged.

So the collapse is a size collapse, not a correctness one. The structure keeps every property it was built for and loses the only reason to prefer it. That distinction matters when reading the plate: a curve running off the top of the axis is usually a structure breaking, and this one is a structure working exactly as specified at a setting nobody should choose.

The same shape appears in in place is a claim, and it is usually wrong about quicksort: an algorithm whose auxiliary space is Θ(logn)\Theta(\log n) rather than Θ(1)\Theta(1) is not broken, it is described wrongly, and the fix is a measurement rather than a repair.

The collapse is a property of the collection as well

The 90% figure is measured on a collection of sixteen identical copies, which is the case where an unbounded parse does best and therefore where a cap does most damage.

On four thousand characters of English-like text with no copying at all, the greedy parse gives 604 phrases — 14.7% of the text — and a cap of one gives 3,764, or 91.9%. The ratio between capped and uncapped is 6.2 rather than 47, because the uncapped parse was not small to begin with.

So the collapse’s size is the collection’s repetitiveness and the collapse’s existence is not. Every text ends up with zz near nn at a cap of one, because every text has about σ\sigma literals and a cap of one leaves nothing else to copy from. The measure that separates texts at the top of the dial does not separate them at the bottom.

A cap of four, on four kinds of textEach bar is the phrase count under a cap of four divided by the phrase count with no cap, on 4,096 characters. The cap costs a text that repeats itself 2.96x the phrases and periodic, period 17 1.11x, and the direction is the opposite of the guess: a periodic text looks like the one made of chains, and its chains are wide and shallow, while a text that repeats itself is copies of copies — which is the thing depth measures. The number beside each bar is the unbounded parse's worst chain on that text.a text that repeats itself2.96xchain 13 · z 110English-like1.31xchain 10 · z 604four symbols, uniform1.28xchain 10 · z 816periodic, period 171.11xchain 9 · z 1,285phrases under a cap of four, against no cap4,096 characters each2.96x to 1.11x
Fig. 4 Four texts under the same cap, as multiples of their own uncapped parse. The multiplier is the text’s business and the destination is not.

What this says about the family of measures

Three quantities have been used in this field to size a structure: an empirical entropy nHknH_k, a run count rr, and a phrase count zz. The phrases a text copies from itself puts all three on one collection and finds two of them flat under copying and one of them not.

The cap adds a fourth reading. zz is the only one of the three whose smallness depends on an unbounded resource, and the resource is the chain a reader walks. nHknH_k has no such dependency — an entropy is a function of a distribution and there is nothing to bound. rr has none either: a run-length index walks a transform, and the number of steps is a property of the query rather than of the parse.

The phrase index is the one structure in the family whose size and whose read cost are traded against each other by the construction, and the cap is the dial that makes the trade explicit. That is worth having even if nobody ever sets it below eight: a measure whose smallness has a hidden cost is better with the cost drawn.

The arithmetic of the collapse, written down

It is short enough to state exactly, and stating it says which quantity in it is the text’s and which is the structure’s.

At a cap of DD, a phrase’s source region must lie entirely at depth below DD. The positions available at depth 0 are the literals, about σ\sigma of them. The positions at depth below 2 are those plus everything the depth-1 phrases produced — and the depth-1 phrases are short, because their sources were single characters — so the available region grows roughly geometrically in DD and the achievable phrase length grows with it.

The phrase count is nn divided by the mean phrase length, so z(D)z(D) falls roughly as the mean achievable match length rises. Measured, the mean phrase length runs 1.11, 2.87, 8.66, 48.2, 52.2 and 52.5 characters at caps of 1, 2, 4, 8, 16 and none — which is the geometric growth, flattening once the cap stops binding.

The quantity that is the text’s in all of this is where it flattens. A text whose repetition is a few long copies flattens early, because a shallow source region already contains a long match; a text whose repetition is copies of copies flattens late. That is the next essay, and it is the one place on this ladder where the measurement contradicts the obvious guess.

The bits, itemised, at the two ends

At a cap of one, over 8,192 characters:

  • phrase lengths: 7,351×137{,}351 \times 13 = 95,563 bits
  • phrase sources: 7,351×137{,}351 \times 13 = 95,563 bits
  • phrase literals: 7,351×57{,}351 \times 5 = 36,755 bits
  • boundary orders: 3×7,351×133 \times 7{,}351 \times 13 = 286,689 bits

Uncapped, over the same characters, the same four rows are 2,028, 2,028, 780 and 3,744.

The boundary orders are the largest row at both ends and they are the row nobody thinks about: three permutations of zz boundaries at log2z\lceil\log_2 z\rceil bits each. At z=156z = 156 that is 3,744 bits, 44% of the index. At z=7,351z = 7{,}351 it is 286,689, 56% of it.

There is a reading of that which flatters the cap and it should be resisted: the boundary orders are cheaper per phrase at a small zz, so a structure with fewer phrases spends proportionally more of itself on the parse and less on the apparatus. It is still sixty times larger overall.

The reason the row is worth naming is that the orders are not the parse. They are the search apparatus — the two orderings a crossing search needs and the rank array the intersection filter reads — and they scale with zlogzz\log z while the parse scales with zlognz\log n. So a cap does not merely make the parse larger; it makes the search structures larger faster than the parse, which is the point the structure paid for before the first query makes about grids from the other direction.

Why the two-copy case is where the whole family lives

One more reading of the sweep, and it is the one that decides whether the cap is a curiosity or a parameter.

The phrase count of an uncapped parse stops growing at the second copy: 155 at one copy, 156 at every point from two to thirty-two. The worst chain does not stop — it is 10 at four copies, 22 at sixteen and 38 at thirty-two. So the gap between what the structure costs and what it costs to read grows without bound as a version history accumulates, and every new version makes the oldest content dearer to reach.

That is the case a bounded-depth parse is actually for. Not a text, and not a collection of a fixed size, but a collection that is still growing — a log, a version-controlled tree, a document with a history — where the size holds still and the read cost quietly does not.

A cap converts that unbounded growth into a fixed premium: nine per cent of the phrases at a cap of eight, at every collection size measured. Whether nine per cent is worth it depends on how often the collection is read, which is what a second pass buys arriving in a different field — a cost paid once against a cost paid per query, and no answer without both counts.

The chain grows with the collection unless something stops itThe worst copy chain across a collection growing to 32 copies, under three caps. With no cap it reaches 38 — one phrase follow per copy, because each copy is parsed as a copy of the one before it — while the phrase count stays at 156. Under a cap of 8 the chain is 8 at every size and the phrase count is 186, which is 1.19x the unbounded one. Both axes are logarithmic.1,00010,00010worst copy chain12481632characters in the collection · copies abovecap 4cap 8cap noneEnglish-like · base 512unbounded reaches 38
Fig. 5 The growth the cap converts into a premium. One line is flat because something stops it and one is flat because nothing does.

The honest limit of these numbers

Three, and the second is the one that would move the headline.

The collection is copies of a generated text. A version history is near-copies, and at one substitution per hundred characters per copy the uncapped phrase count no longer stops growing — which means the 47-fold ratio at a cap of one is measured at the most favourable point for the uncapped parse and is an upper bound on what a real corpus would show.

The sizes are what this accounting charges. A phrase costs 2log2n+log2σ2\lceil\log_2 n\rceil + \lceil\log_2\sigma\rceil bits here, which is a fixed-width encoding of the source and the length. A real implementation encodes lengths with a variable-width code, and short phrases — which is what a tight cap produces — are exactly where such a code wins most. So the collapse at a cap of one is real and its measured size is a property of the encoding as much as of the parse.

And nothing here is timed. Every quantity is a count: phrases, bits, phrase follows, character comparisons. That is this collection’s method rather than a limitation, and it is what makes a factor of sixty a statement about structure rather than about a machine — but it also means the question “is a cap of eight worth nine per cent” cannot be settled here, because the answer depends on the relative price of a bit and a follow on hardware nobody has specified.

Where else a constraint has undone a compression

Two neighbours in this collection, both of which are the same arithmetic under other names.

A sampling that costs more than the array is the closest. A run-boundary sampling exists to remove a term proportional to the text and, on four-symbol text where runs are short, costs 2.07 times the whole suffix array it replaced. Same shape: a structure sized by a measure, and a text where the measure is not small.

The optimal code that is beaten is the version in coding. A prefix code is optimal among prefix codes and is beaten by an arithmetic coder, because the optimality was conditional on a constraint — whole numbers of bits per symbol — that the comparison did not share.

And the model a bound was quoted in is the general statement: every bound in this collection is conditional on a model, the model is usually implicit, and a claim carried outside its model is a claim about nothing. The phrase count’s smallness is conditional on an unbounded chain, and the cap is what makes the condition visible by removing it.

The entropy cannot see a copy, and the run count sees nothing elseEnglish-like of 512 characters, repeated. The upper curve is n·H₃ — the bound every compressed self-index on this site is measured against — which grows 15.8x across a collection that grew 16.0x, because the distribution of symbols in three-symbol contexts is the same in two copies as in one and the second copy is charged full price. The lower curve is r, the number of equal-letter runs in the Burrows-Wheeler transform, which is 224 at two copies and 224 at 32 — it does not move at all. The copies here are identical. Both axes are logarithmic.1,00010,00010³10⁴bits · runs12481632characters in the collection · copies aboven·H₃, bitsr, runs in thetransformEnglish-like · base 512 · divergence 0n·H₃ x15.8 · r x1.00
Fig. 6 Every size of the same collection, from the raw file down through the entropies — the scale a structure at ninety per cent of the text has fallen off.

What is being claimed

A cap of one takes the phrase count from 1.9% of the text to 89.7% of it, on a collection of sixteen copies, and the index from 8,580 bits to 514,570.

The reason is the alphabet-sized floor. Depth zero is the literals, there are about σ\sigma of them, and a source region of one character supports a match of one character.

Every text ends up there. The multiplier is the text’s repetitiveness — 47 on a collection of copies, 6.2 on ordinary text — and the destination is about 90% of the characters in both cases.

And the term comes back gradually. It is 2.1% of the text at a cap of eight and 11.5% at four, so the collapse is a feature of the tight end of the dial rather than of capping as such. A reader who wanted one sentence for it: the phrase count is small because the parse may reach arbitrarily far back through arbitrarily many copies, and any bound on how far it reaches is a bound on how small it can be.

A cap is not free to enforce, eitherCharacter comparisons performed by the greedy parse under each cap, on 2,048 characters. The unbounded parse makes 2,754 of them and a cap of 2 makes 85,709 — 31x as many — because a capped parse takes shorter phrases and therefore has more of them to find, and each one is a scan over everything earlier. The construction is quadratic either way; the cap multiplies its constant.cap 285,709725 phrasescap 435,754247 phrasescap 85,170101 phrasescap none2,75499 phrasescharacter comparisons during the parseEnglish-like · 2,048 characters31x at the tightest cap
Fig. 7 And the last column: what it costs to compute the parse that produced any of this, which grows faster than anything else in the sweep.

The knee has a location, and the four measurements bracket it tightly. The phrase count is 1.9% of the text uncapped, 2.1% at a cap of eight, 11.5% at four, and 89.7% at one — so it is flat, then a factor of five, then a factor of eight.

The collapse happens between a cap of four and a cap of two, and everything looser than four is indistinguishable from no cap at all. That is a narrower statement than the tight end of the dial and it is the one a reader choosing a cap needs: eight is free, four is a fivefold cost that may still be worth a bounded read, and anything below it is the term returning in full.

What this makes readable

Essays that name this one as a prerequisite.

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.

AlphabetBounded depth parseCompressibilityCopy depthIndex sizeLempel ziv parseMeasurementPhraseRepetitionSelf-indexSpace overheadTrade off