The data that is not a number

A paragraph rewritten, not a letter changed

Every collection of copies measured so far drifted by flipping single characters at random, and a real repetitive collection changes a paragraph at a time. At the same share of characters changed, the shape matters by an order of magnitude: across thirty-two copies of one text a scattered substitution adds 4.6 runs to the transform and 1.9 phrases to the parse, and a rewritten block of 64 characters adds 24 runs and 12 phrases — 0.38 runs a changed character against 4.6. With 2% of the copies changed, scattered edits put the run count at a tenth of a character and hand the smallest index to the entropy-bounded one; the same 2% in blocks of 16 leaves both repetition indexes far under it. A block's phrases follow two plus its length over 7.5, the mean phrase of fresh text, and phrases over runs never comes near the 1.28 at which the r-index would become the smaller.

The collection decides which index is small set three compressed self-indexes against each other and reduced the contest to three constants. On collections of copies of one English-like text, the phrase index built on the Lempel–Ziv parse cost about 57 bits a phrase, the r-index built on the runs of the Burrows–Wheeler transform about 73 bits a run, and the entropy-bounded FM-index about 2.11 bits a character. So the phrase index is smaller than the entropy-bounded one when the parse has fewer than 0.037 phrases a character, the r-index when the transform has fewer than 0.029 runs a character, and the phrase index is smaller than the r-index whenever phrases over runs is under 1.28.

Its honest limit named what those collections were not. Every collection in the strand that started with the entropy that cannot see a copy was a set of copies that had drifted apart by scattered substitutions: each character of each copy flipped to a random symbol with some small probability. A real repetitive collection does not drift that way. A version history changes a paragraph and leaves the rest alone; a set of near-duplicate pages differs in a block of navigation or a date. Both measures, the essay said, respond to the difference — and it did not say how much.

Two ways to change two per cent

The collection is the strand’s own: thirty-two copies of a 512-character English-like text, sixteen thousand characters in all. With every copy identical the transform has 224 runs and the parse 161 phrases, 0.014 and 0.010 a character, which is far under both thresholds; the phrase index is the smallest of the three.

Then each copy after the first has a share of its characters changed, in one of two shapes. Scattered: every character independently, as before. In blocks: a stretch of LL consecutive characters, at a random place in a random copy, rewritten with fresh text drawn from the same source, for LL of 4, 16, 64 and 256 — as many blocks as the share requires. The share changed is the same in both shapes, up to the rounding of a few long blocks, and every plate plots against the share that actually changed. Four collections are drawn at every setting.

With 2% of the copies' characters changed, scattered substitutions put the run count at 0.100 a character, past the 0.029 under which the r-index is smaller than the entropy-bounded index; rewritten in blocks of 16 the same share leaves it at 0.026. Scattered changes cross the line between 0.2% and 0.5% changed (0.037 at 0.5%), blocks of 16 between 2% and 5% changed (0.045 at 5%), blocks of 64 between 2% and 5% changed (0.031 at 5%)Thirty-two copies of a 512-character English-like text, each copy after the first with a share of its characters changed, as scattered substitutions or as blocks rewritten with fresh text of the same source, four collections a setting. runs a character, r/n against the share actually changed: scattered substitutions: 0.2% 0.023, 0.5% 0.037, 1.0% 0.058, 2% 0.100, 5% 0.217, 10% 0.370; blocks of 4: 0.2% 0.017, 0.5% 0.021, 1% 0.029, 2% 0.045, 5% 0.092, 10% 0.164; blocks of 16: 0.2% 0.015, 0.5% 0.017, 1% 0.020, 2% 0.026, 5% 0.045, 10% 0.074; blocks of 64: 0.4% 0.015, 0.8% 0.017, 2% 0.021, 5% 0.031, 10% 0.050; blocks of 256: 2% 0.018, 2% 0.018, 5% 0.027, 10% 0.040. Identical copies: 0.014. Dashed: r-index smaller below, 0.0289.0.2%0.5%1%2%5%10%0.020.050.10.2share of the copies' characters changed (log scale)runs a character, r/n (log scale)scattered substitutionsblocks of 4blocks of 16blocks of 64blocks of 256r-index smaller belowidentical copies32 copies of 512 characters4 collections a point
Fig. 1 Runs of the transform a character against the share of the copies changed, for scattered substitutions and for blocks of 4 to 256, with the line under which the r-index is smaller than the entropy-bounded index and the level of identical copies.

The two shapes separate at once. With 2% of the copies’ characters changed, scattered substitutions put the transform at 0.100 runs a character — more than seven times identical copies’ 0.014, and more than three times the 0.029 under which the r-index is the smaller structure. The same 2% rewritten in blocks of 16 leaves it at 0.026, still under the line. Scattered changes cross the r-index’s line between 0.2% and 0.5% changed. Blocks of 16 cross it between 2% and 5%, and blocks of 64 between 2% and 5% too, but only just: 0.031 at 5%.

So the strand’s whole account of when the r-index is the right structure was drawn on the shape of change least favourable to it. A collection that has drifted by a twentieth of its characters in paragraphs is still in the regime the r-index was built for; one that has drifted by a two-hundredth of its characters at random is not.

Phrases follow the same rule

Phrases a character against the 0.037 under which the phrase index beats the entropy-bounded one: scattered substitutions cross it between 1% and 2% changed (0.045 at 2%), blocks of 4 between 5% and 10% changed (0.058 at 10%), blocks of 16 not by 10% changed (0.033)Thirty-two copies of a 512-character English-like text, each copy after the first with a share of its characters changed, as scattered substitutions or as blocks rewritten with fresh text of the same source, four collections a setting. phrases a character, z/n against the share actually changed: scattered substitutions: 0.2% 0.014, 0.5% 0.019, 1.0% 0.028, 2% 0.045, 5% 0.091, 10% 0.152; blocks of 4: 0.2% 0.011, 0.5% 0.013, 1% 0.015, 2% 0.021, 5% 0.035, 10% 0.058; blocks of 16: 0.2% 0.011, 0.5% 0.011, 1% 0.013, 2% 0.015, 5% 0.022, 10% 0.033; blocks of 64: 0.4% 0.011, 0.8% 0.012, 2% 0.014, 5% 0.018, 10% 0.026; blocks of 256: 2% 0.012, 2% 0.012, 5% 0.017, 10% 0.023. Identical copies: 0.010. Dashed: phrase index smaller below, 0.037.0.2%0.5%1%2%5%10%0.010.020.050.1share of the copies' characters changed (log scale)phrases a character, z/n (log scale)scattered substitutionsblocks of 4phrase index smaller belowblocks of 16blocks of 64blocks of 256identical copies32 copies of 512 characters4 collections a point
Fig. 2 Phrases of the parse a character against the share changed, for each shape, with the line under which the phrase index is smaller than the entropy-bounded index.

The parse responds the same way, less steeply. Scattered substitutions push it over the phrase index’s threshold of 0.037 phrases a character between 1% and 2% changed; blocks of 4 between 5% and 10%; blocks of 16 not by 10%, where they sit at 0.033. The phrase index stays smaller than the entropy-bounded one up to five times as much change when the change comes in paragraphs.

What one edit costs

The reason is in the unit each measure counts. A run of the transform ends wherever two adjacent rows of the sorted rotations are preceded by different characters, and a phrase of the parse ends wherever the text stops repeating something earlier. A change breaks both at the place it happens, and the characters inside a changed block mostly do not break anything new.

One rewritten block adds about 10.11 runs and 4.25 phrases at 16 characters and 72.46 and 35.75 at 256; a scattered substitution adds 4.61 and 1.89. The phrases follow two plus the block's length over 7.52, the mean phrase of fresh text against the collectionThirty-two copies of 512 characters; runs and phrases added over identical copies, divided by the number of edit sites, pooled over every edited share with at least four sites a collection. scattered: 4.61 runs, 1.89 phrases a site (6 shares); blocks of 1: 4.10 runs, 1.69 phrases a site (6 shares); blocks of 4: 6.39 runs, 2.20 phrases a site (6 shares); blocks of 16: 10.11 runs, 4.25 phrases a site (5 shares); blocks of 64: 24.27 runs, 11.72 phrases a site (3 shares); blocks of 256: 72.46 runs, 35.75 phrases a site (1 shares). Least-squares fit of phrases a site − 2 against L through the origin: ℓ = 7.52.020406080length of a rewritten block (log scale)added by one edit site141664256runs a sitephrases a site2 + L / 7.52scattered: 4.61 runs, 1.89 phrases a siteper edit site
Fig. 3 Runs and phrases added by one edit site, against the block’s length, pooled over every share with at least four sites a collection, with the fitted line for phrases.

A scattered substitution adds 4.6 runs and 1.9 phrases. A rewritten block of 4 adds 6.4 and 2.2; of 16, 10.1 and 4.3; of 64, 24 and 12; of 256, 72 and 36. The phrases follow a simple rule closely: two plus the block’s length over 7.5. The two are the phrases that break at the block’s edges — the copy’s text stops matching where the block starts and resumes matching where it ends — and the rest is the block’s own fresh text, which the parse covers in phrases of about 7.5 characters by finding pieces of it elsewhere in the collection. That is the same mechanism an index with z in its size built on: a phrase is a pointer to an earlier occurrence, and fresh English-like text has short earlier occurrences everywhere.

The runs grow more slowly than the block’s length, roughly with its three-quarter power: four times the block costs between two and a half and three times the runs. A changed character inside a block changes the rotations that start near it, but rotations starting inside fresh text are sorted among the collection’s other rotations by their own first characters, and many of them land beside rotations with the same preceding character. A run is broken only where the preceding characters differ, and inside a block of fresh text they often do not.

Edges and contents

The two measures can be split into what a block costs at its edges and what it costs inside, and the split says where the remaining runs come from.

For phrases the split is clean, because the fitted rule is already in that form: two phrases for the edges, one for every 7.5 rewritten characters. For runs it is rougher. Between blocks of 64 and 256 the runs added grow by 48 for 192 more characters, a quarter of a run a character, and extending that line back to a block of nothing leaves about eight runs for the edges — more than the four or five a single scattered substitution costs, because a block’s two edges each join fresh text to old text in a context none of the copies has had, where a substitution makes one such junction on each side of one character. For short blocks the line overstates: blocks of 4 and 16 cost 6.4 and 10.1 runs, under the line’s 9 and 12, because their edges and their contents overlap.

A quarter of a run for every rewritten character is a measurable fraction of what the same source costs when it is not repeated at all. The original 512-character text, on its own, has 0.43 runs and 0.31 phrases a character. A rewritten block costs less than that inside — 0.25 runs and 0.13 phrases a character — because its fresh text is fresh to its copy but not to the collection: the other thirty-one copies, and the other blocks, are full of the same three- and four-character pieces, and the parse points at them while the transform sorts its rotations beside theirs.

So a long block costs about what that much new text would, and a scattered change costs about eighteen times what one character inside a long block does. Everything in the comparison follows from those two facts: scattered changes are all edges, and blocks are mostly contents.

A changed character, priced

A changed character costs 4.61 runs and 1.89 phrases when the changes are scattered, 0.38 and 0.18 when they come in blocks of 64 — 12 times fewer runs for the same characters changedThirty-two copies of 512 characters: runs and phrases added over identical copies, divided by the characters actually changed, pooled over every edited share with at least four sites. scattered substitutions: 4.607 runs, 1.886 phrases a changed character; blocks of 1: 4.102 runs, 1.685 phrases a changed character; blocks of 4: 1.597 runs, 0.549 phrases a changed character; blocks of 16: 0.632 runs, 0.266 phrases a changed character; blocks of 64: 0.379 runs, 0.183 phrases a changed character; blocks of 256: 0.283 runs, 0.140 phrases a changed character.scattered substitutions4.61 runs1.89 phrasesrewritten, blocks of 14.10 runs1.69 phrasesrewritten, blocks of 41.60 runs0.55 phrasesrewritten, blocks of 160.63 runs0.27 phrasesrewritten, blocks of 640.38 runs0.18 phrasesrewritten, blocks of 2560.28 runs0.14 phrases32 copies of 512 charactersa changed character
Fig. 4 Runs and phrases added a changed character, by the shape of the change. The same characters changed cost twelve times fewer runs when they come in blocks of 64.

Divided by the characters changed rather than the places, the difference is the size of the effect. A scattered change costs 4.6 runs and 1.9 phrases a character. In blocks of 4 it is 1.6 and 0.55; of 16, 0.63 and 0.27; of 64, 0.38 and 0.18 — twelve times fewer runs and ten times fewer phrases than the same characters changed one at a time; of 256, 0.28 and 0.14.

That is why “divergence”, the dial the earlier essays used, is not a property of a collection anyone could quote without saying what kind. Two collections each 2% different from their original can differ by a factor of four in run count and the r-index built on them by the same factor, and the number that predicts which is not how much changed but how many places it changed in. The index that stores the runs was right that the run-length index’s size follows the runs and not the characters; this is the same statement one level down, about what the runs follow.

Which index is smallest

Priced by the earlier essay's constants, the phrase index is the smallest of the three on every collection with blocks of 16 or 64 up to 10% changed; scattered substitutions hand it to the entropy-bounded index from 2% changed, and blocks of 4 from 10% — the r-index is never the smallest, as the earlier essay's z/r < 1.28 requiredThirty-two copies of 512 characters; the three sizes from the measured constants — 57 bits a phrase, 73 a run, 2.11 a character — and which is smallest, at each edited share and shape. scattered substitutions: 0.2% phrase (12,825, 27,393, 34,570), 0.5% phrase (18,069, 44,238, 34,570), 1% phrase (26,462, 69,916, 34,570), 2% entropy (42,038, 119,629, 34,570), 5% entropy (85,443, 259,205, 34,570), 10% entropy (141,802, 442,855, 34,570); blocks of 4: 0.2% phrase (10,232, 20,002, 34,570), 0.5% phrase (11,756, 25,696, 34,570), 1% phrase (14,393, 35,223, 34,570), 2% phrase (19,181, 54,221, 34,570), 5% phrase (32,975, 109,902, 34,570), 10% entropy (54,307, 195,567, 34,570); blocks of 16: 0.2% phrase (9,818, 18,049, 34,570), 0.5% phrase (10,488, 20,166, 34,570), 1% phrase (11,756, 23,853, 34,570), 2% phrase (14,008, 30,624, 34,570), 5% phrase (20,919, 53,418, 34,570), 10% phrase (30,452, 88,002, 34,570); blocks of 64: 0.2% phrase (9,177, 16,352, 34,570), 0.5% phrase (10,061, 18,451, 34,570), 1% phrase (10,745, 20,112, 34,570), 2% phrase (12,797, 25,386, 34,570), 5% phrase (17,243, 37,449, 34,570), 10% phrase (24,382, 60,116, 34,570). Counts: scattered phrase 3, entropy 3, r-index 0; 4 phrase 5, entropy 1, r-index 0; 16 phrase 6, entropy 0, r-index 0; 64 phrase 6, entropy 0, r-index 0.share of the copies' characters changed0.2%0.5%1%2%5%10%scattered substitutionsblocks of 4blocks of 16blocks of 64phrasephrasephraseentropyentropyentropyphrasephrasephrasephrasephraseentropyphrasephrasephrasephrasephrasephrasephrasephrasephrasephrasephrasephrasecells: the smallest of the phrase index, the r-index and the entropy-bounded index32 copies of 512 charactersconstants from the earlier essay
Fig. 5 Which of the three indexes is smallest, priced by the earlier essay’s constants, at each share changed and each shape. The r-index never is; the boundary between the phrase index and the entropy-bounded index moves with the shape of the change.

Priced by the three constants, the phrase index is the smallest structure on every collection whose changes come in blocks of 16 or 64, up to 10% changed. Blocks of 4 hand the place to the entropy-bounded index at 10%. Scattered substitutions hand it over from 2% changed, which is where the earlier essays’ collections spent most of their time.

The r-index is never the smallest, which the earlier essay’s third threshold already said: it is never smaller than the phrase index unless phrases over runs exceeds 1.28. That essay’s reason for recommending it anyway was not size but its costs — every occurrence at the same price is the argument — and nothing here touches that. What changes is the size it pays for those costs: on a collection that changes in paragraphs it stays within about twice the phrase index’s size and far under the entropy-bounded index’s, up to a twentieth of the text changed.

The ratio that would reverse the order

Phrases over runs stays between 0.36 and 0.70 on every collection — under the 1.28 at which the r-index would become the smaller of the two repetition indexes — falling as scattered changes multiply runs faster than phrases and rising back toward identical copies' 0.72 as the changes clusterThirty-two copies of 512 characters: z/r against the share changed, by edit shape. scattered substitutions: 0.2% 0.60, 0.5% 0.52, 1.0% 0.48, 2% 0.45, 5% 0.42, 10% 0.41; blocks of 4: 0.2% 0.66, 0.5% 0.59, 1% 0.52, 2% 0.45, 5% 0.38, 10% 0.36; blocks of 16: 0.2% 0.70, 0.5% 0.67, 1% 0.63, 2% 0.59, 5% 0.50, 10% 0.44; blocks of 64: 0.4% 0.70, 0.8% 0.68, 2% 0.65, 5% 0.59, 10% 0.52; blocks of 256: 2% 0.69, 2% 0.69, 5% 0.63, 10% 0.57. Identical copies 0.72; the earlier essay's crossing 1.28.0.2%0.5%1%2%5%10%00.50011.50share of the copies' characters changed (log scale)phrases over runs, z/rr-index smaller aboveblocks of 256blocks of 64blocks of 16scattered substitutionsblocks of 432 copies of 512 charactersz / r
Fig. 6 Phrases over runs against the share changed, by shape, with the 1.28 at which the r-index would become the smaller of the two repetition indexes.

Phrases over runs is 0.72 for identical copies, and every kind of change lowers it, because every change breaks more runs than phrases. Scattered substitutions bring it to 0.41 at 10% changed; blocks of 64 only to 0.52; blocks of 256 to 0.57. Across every collection it stays between 0.36 and 0.70. The earlier essay found it between 0.26 and 0.71 on the texts it measured and called the third threshold “not close”; clustered changes keep it nearer the identical-copy end of that range, and still far from 1.28.

The earlier essay named the one condition that could reach it: an adversarial order of the alphabet, which moves the run count and not the parse, as the measure that cannot see the alphabet constructed. The shape of a collection’s edits is not that condition. Nothing about rewriting paragraphs instead of letters makes runs cheaper than phrases.

What the third measure does

The entropy-bounded index is drawn on every plate as a fixed 2.11 bits a character, and that is the earlier essay’s constant, not a measurement of these collections. The entropy that cannot see a copy is the reason it does not move with the number of copies; it does move with the changes. The order-three entropy of thirty-two identical copies is 0.59 bits a character; with 2% scattered substitutions it is 0.71, and with 10% it is 1.14, because every substituted character creates contexts the original never had. The earlier essay measured the FM-index at 3.4 times its order-three entropy; if it tracked the entropy in that proportion, the entropy-bounded index on the scattered collections would have grown by a fifth at 2% and nearly doubled at 10%. It was not rebuilt to check.

Holding it at 2.11 is therefore generous to it on scattered changes, and the boundary on the smallest-index plate would sit at somewhat larger shares if it were rebuilt. Rewritten blocks of fresh text from the same source barely move the entropy, since their contexts are the source’s own, so on the clustered collections the fixed constant is close to right. The comparison between shapes survives the correction and becomes a little sharper.

The r-index’s constant has the opposite problem. What is still proportional to n found that at thirty-two copies about half the run-length index is its suffix-array sampling, which follows the text’s length rather than its runs; the 73 bits a run of the earlier essay already contains that, spread over the runs. On a collection with more runs the sampling is a smaller share of the whole and the constant falls a little. None of the thresholds moves by enough to change which shape crosses where.

What to ask of a collection before choosing

The practical reading is short. The earlier essay’s decision asked two numbers of a collection, its runs and its phrases a character, and both cost one pass to measure. This essay adds a reason to measure them rather than estimate them from how different the documents are said to be: the same stated difference spans a factor of three to five in both — at 2% changed, 1,639 runs scattered against 348 in blocks of 64, and 738 phrases against 225 — and which side of a threshold a collection falls on depends on the shape of its differences, which nobody quotes.

A collection that grows by appending revised versions — a wiki’s history, a sequence of releases, a set of near-duplicate pages — changes in blocks, and on it the repetition indexes keep their advantage far longer than the strand’s own collections suggested. A collection whose copies differ by noise — sequencing errors, typing errors, a lossy channel — changes in scattered characters, and on it they lose it early. The two kinds look alike if the only number quoted is the share that differs.

What the rewritten blocks are not

Fresh text from the same source. A rewritten block is drawn from the same English-like generator as the original, so its pieces occur elsewhere in the collection and the parse covers it in phrases of 7.5 characters. A block of text from a different language, or of random characters, would parse into shorter phrases and cost more of both measures; a block that moves a paragraph rather than rewriting it — the commonest edit in a real history — would cost almost nothing, two phrases and a few runs at its edges. Neither was measured, and they bracket the case measured here from both sides.

One collection shape. Thirty-two copies of 512 characters, the strand’s standard. More copies of a longer text lower identical copies’ runs and phrases a character further, and give every shape of change more room before a threshold; the order of the shapes should not change.

Constants, not indexes. The three index sizes are the earlier essay’s constants multiplied by the measured runs, phrases and length; none of the three structures was rebuilt for these collections. The constants were measured on collections of exactly this shape and the thresholds follow from them, so the comparison is between collections rather than between implementations.

A corpus that was not generated froze a real version history so that measurements about one would be about a fixed object, and that history is the natural place to read what shapes of change real collections actually have.

Still open: a paragraph that moves

The rewritten block is the middle case of three. A collection’s edits can also move text — a paragraph cut from one place and pasted in another, the same characters in a different order — and a moved block changes no character’s content at all. The parse should see it as two broken phrases and one long pointer to the block’s old place; the transform should see it as a few rotations at the block’s edges sorting into new neighbours.

The measurement that follows changes the copies by moving blocks of 16 to 256 characters to random places within the same copy, at the same shares of characters moved, and puts the three shapes on one plate. The prediction is that a moved block costs about four phrases and eight runs whatever its length, so that a collection with a tenth of its text moved in blocks of 64 stays at about identical copies’ sizes, and that the run-length structure’s advantage over the entropy-bounded index survives up to a much larger share moved than rewritten. It could fail at the block’s edges: a moved block creates two new junctions per move, and each junction is a pair of contexts no copy has had, which the transform may punish more than the parse. The question is whether the measures count what changed or only where, and a move is the edit that separates the two.

Named alongside this one

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

The objects this essay names

Each one links to every other essay that touches it.

Burrows-wheeler transformCompressibilityFM-indexHonest limitIndex sizeInformation contentLempel ziv