The index that replaces the text

One doubling late

A document array coded by its documents' lengths and refitted each time a growing directory's files double needs an escape for the files added in between, and the escape's right weight is the share of the characters still to come. Weighting it by the share that arrived since the previous refit was predicted to cut the mean loss below a quarter of a bit a symbol. It cuts nothing: 0.518 bits a symbol, against 0.389 for an escape that always takes half the coding space. The growth seen is the growth to come one doubling late — 71%, 50% and 27% where the doublings that followed brought 50%, 27% and 8% — because this directory's growth slowed at every doubling, and before the first refit there is no growth to read at all. A Huffman code also rounds every weight to a whole number of bits, so being right within a factor of two buys nothing. Started from half, the growth seen averages 0.356, the best a store can know, and the weight nobody can know reaches 0.183.

The shape arrived early and the bytes late replayed a project’s source directory through its history, from twenty files to 222, and kept the directory’s document array, one entry per character naming the file it belongs to, coded by a Huffman code over the files’ lengths. A code fitted at one version needs a way to name files that arrive later, and it has one: an escape, a code word that says “a file added since the fit”, followed by a small code over the added files. The essay found that the spread of the files’ sizes was settled early, and that the loss came from somewhere else. The files added after a fit hold most of the final bytes, and every one of their characters pays the escape’s code word.

A document array’s symbols are its documents and their frequencies are the documents’ lengths, so its entropy is the length distribution’s, which the array is the length distribution showed exactly; the collections the saving was quoted for measured what that saves on real collections, a tenth of the plain array on this directory taken whole. The best schedule the history essay measured refitted the Huffman code whenever the number of files doubled and rebuilt only the escape’s subtree in between, an average loss of 0.39 bits a symbol for rewriting 5.65 times the final array. Its closing section named the weak point. The escape’s weight decides its code word, and the right weight is the share of the characters that will arrive after the fit, which nobody knows. The history so far is the only evidence. So it proposed weighting each refit’s escape by the share of the current characters that arrived since the previous refit, the growth already seen, and predicted the mean loss would fall below a quarter of a bit, at under three times the final array rewritten. It could fail on spurts: a doubling that arrives in a few versions would be weighted by the slow growth before it, and the escape would always be one spurt behind.

Five weights for one schedule

Every schedule here is the earlier essay’s best: refit at versions 0, 10, 22 and 44, where the files reach 20, 40, 81 and 175, and rebuild the escape’s subtree at every version in between from the added files’ own lengths. Only the escape’s weight at each refit differs, so every schedule reads exactly the same bytes, 5.65 times the final array. The prediction’s three times was about a schedule this one is not; the rewriting belongs to the refits, and no weight changes it.

The weights are given as the escape’s share of the coding space. As one document is the earlier essay’s default, the average file’s share. As half the coding space is the earlier essay’s other escape, weighted as the whole collection. By the growth seen is the proposal: at each refit, the share of the current characters held in files added since the previous refit; the first refit has nothing before it and takes the one-document weight. Growth seen, half at first is the same with the half weight at the first refit. By the growth to come is the weight nobody has: the share of the characters at the next refit held in files added after this one. It is the scale against which the others are measured.

The loss at a version is its bits a symbol against the Huffman code refitted at that version, the best a code of this kind can do there. With the one-document weight the schedule is the earlier essay’s to the bit at every version, which is the check that nothing else changed.

The loss through the history

Weighted by the growth seen since the last refit, the escape loses 0.518 bits a symbol on average over the directory's history, against 0.389 for an escape always weighted as half the coding space and 0.183 for the weight nobody can know, the growth still to comeBits a symbol of the document array at each of 47 versions, over the Huffman code refitted at that version, for a Huffman code refitted at every doubling of the files (versions 0, 10, 22, 44) with the escape's subtree rebuilt between, the escape weighted four ways. as one document: mean 0.622, largest 1.910, last 0.250. as half the coding space: mean 0.389, largest 1.000, last 0.593. by the growth seen: mean 0.518, largest 1.910, last 0.138. by the growth to come: mean 0.183, largest 1.000, last 0.006.00.50011.5020102244version of the directory (grey lines: a refit at a doubling)bits a symbol over the Huffman code refitted thereas half the coding spaceas one documentby the growth seenby the growth to come20 files to 222, a refit at each doublingthe escape's weight is all that differs
Fig. 1 Bits a symbol over the refitted code at each of 47 versions, refits at versions 0, 10, 22 and 44. As one document: up to 1.91 before the first refit, mean 0.622. As half the coding space: never above 1.00, mean 0.389. By the growth seen: mean 0.518. By the growth to come: mean 0.183.

Weighted by the growth seen, the escape loses 0.518 bits a symbol on average over the history, more than the 0.389 of an escape that always takes half the coding space; the prediction was under a quarter of a bit. The weight nobody can know, the growth still to come, reaches 0.183, so the escape’s weight is worth about a fifth of a bit a symbol across the history. The growth seen captures none of it on its own, and with a half-weight start about a sixth.

The plate shows where. Before version 10 the growth seen has nothing to read and takes the one-document weight, and the loss climbs to 1.91 bits as the added files grow to two thirds of the directory. After the first refit it tracks the half-weight escape exactly for a stretch, and only in the last stretch, after version 44, does it pull clear of it.

The past is the future one refit late

The growth seen is the growth to come one doubling late: at the refits after the first, the past says 71%, 50%, 27% of the characters are new, and the doubling that followed each brought 50%, 27%, 8% — the same numbers, shifted by one refit, because the directory's growth slowed at every doublingAt each refit of the doubling schedule (versions 0, 10, 22, 44, 20, 40, 81, 175 files), the escape's weight as a share of the coding space under each rule: the share of current characters in documents added since the previous refit (the growth seen), the share at the next refit in documents added after this one (the growth to come), half, and one document. version 0: by the growth seen 5%, by the growth to come 71%, as half the coding space 50%, as one document 5%. version 10: by the growth seen 71%, by the growth to come 50%, as half the coding space 50%, as one document 2%. version 22: by the growth seen 50%, by the growth to come 27%, as half the coding space 50%, as one document 1%. version 44: by the growth seen 27%, by the growth to come 8%, as half the coding space 50%, as one document 1%.0%25%50%75%100%the escape's share of the coding spaceversion 020 filesversion 1040 filesversion 2281 filesversion 44175 filesin each group: growth seen, growth to come, half, one documentat each refit
Fig. 2 The escape’s share of the coding space at each refit. By the growth seen: 5% (one document), 71%, 50%, 27%. By the growth to come: 71%, 50%, 27%, 8%. As half the coding space: 50% throughout. As one document: 5%, 2%, 1%, 1%.

At the refits after the first, the growth seen says 71%, 50% and 27% of the characters are new; the doublings that followed brought 50%, 27% and 8% — the same numbers, one refit late. The proposal reasoned that the growth since the last refit was the best evidence of the growth to come. In this directory it is exactly the growth to come of the previous refit, and that is not a coincidence of the numbers. Each refit happens when the files double, so the share of characters in files added during the stretch just finished is the stretch’s growth; the next stretch is another doubling of files, and here each doubling brought a smaller share of the characters than the one before. Either the files added late are smaller than those already there, or the old files grew while new ones arrived, or both; the replay does not separate them.

The earlier essay’s closing section expected the share at each doubling to be a little under half, which would have made the past a good guess for the future. It is a little under half once, at the second refit. Before that it is more, after it much less, and a guess that is always the last stretch’s share is always too large on a directory whose stretches shrink.

Weights, in whole bits

A Huffman code turns the escape's weight into a whole number of bits, so weights within a factor of two give the same code word: at the four refits the growth seen gives the escape 4, 1, 1, 2 bits and half the coding space 1, 1, 1, 1 — the same at the two middle refits, where 71% and 50% both round to one bit — and the growth to come asks for 0.50, 1.00, 1.90, 3.62The length in bits of the escape's code word at each refit (versions 0, 10, 22, 44) under each weight, and the length the growth to come would ideally give it, −log₂ of its share. as one document: 4, 5, 6, 8. as half the coding space: 1, 1, 1, 1. by the growth seen: 4, 1, 1, 2. by the growth to come: 1, 1, 2, 4. Ideal: 0.50, 1.00, 1.90, 3.62.012345678the escape's code word, bitsversion 0version 10version 22version 44bars: one document, half, growth seen, growth to come · line: the idealat each refit
Fig. 3 The escape’s code word in bits at each refit, and the length the growth to come would ideally give it. As one document: 4, 5, 6, 8. As half the coding space: 1, 1, 1, 1. By the growth seen: 4, 1, 1, 2. By the growth to come: 1, 1, 2, 4. Ideal: 0.50, 1.00, 1.90 and 3.62 bits.

A Huffman code gives the escape a whole number of bits, so weights within a factor of two give the same code word: at the second and third refits the growth seen, 71% and 50%, and the half weight both give the escape one bit. That is why the two schedules have identical losses through the middle of the history. Getting the weight right within a factor of two buys nothing; only a weight that crosses a power of two changes the code word.

The ideal lengths say what crossing is worth. At version 44 the growth to come asks for 3.62 bits; the half weight gives 1, which over-pays the escape’s mass and starves every old file of a little code space, and the one-document weight gives 8, which over-charges every new character. The growth seen gives 2, closer than either, and that is the one stretch it wins. A code word is at least one bit found the same floor on the other side: an escape that should cost half a bit, as at the first refit, cannot cost less than one.

Why a fixed half does so well for so long

The half weight looks naive, a guess that half the coding space belongs to files not yet seen, and it beats the rule built from evidence for most of the history. The plate of code words says why. A half weight gives the escape a one-bit code word at every refit. At the first two refits the growth to come asks for 0.50 and 1.00 bits, so one bit is the best a whole-bit code can do there, and the half weight is, by accident, the oracle’s code. It goes wrong only when the growth to come falls below a quarter, at the third refit, and badly when it falls below an eighth, at the fourth.

The growth seen is the opposite kind of guess. It has nothing at the first refit and so takes a weight of one document, a code word of four bits for files that will hold two thirds of the characters. After that it is one doubling late, which on this directory means always too large, but too large by less than a factor of two until the end, and so one bit, like the half weight, until the last refit gives it two.

Neither guess is reading the right thing. The quantity that sets the escape’s code word is the power of two nearest the share still to come. A rule that cannot know that share does best by being right about its order of magnitude, and on a directory whose growth slows each time, a fixed guess is right at the start and the evidence of the past is right at the end.

Stretch by stretch

The growth seen has nothing to read before the first refit, and there it loses 1.043 bits a symbol where half the coding space loses 0.280; after it, it ties half the coding space for two stretches and wins the last, 0.253 against 0.767 — started from half, it averages 0.356Mean bits a symbol over the refitted Huffman code in each stretch between refits (versions 0–9, 10–21, 22–43, 44–46) for each weight. as one document: 1.043, 0.793, 0.404, 0.127. as half the coding space: 0.280, 0.216, 0.481, 0.767. by the growth seen: 1.043, 0.216, 0.481, 0.253. growth seen, half at first: 0.280, 0.216, 0.481, 0.253. by the growth to come: 0.280, 0.216, 0.142, 0.034.00.250.50.751mean bits a symbol over the refitted Huffman codeversions 0–9versions 10–21versions 22–43versions 44–46in each group: one document, half, growth seen, growth seen from half, growth to comebetween refits
Fig. 4 Mean bits a symbol over the refitted code between refits. Versions 0–9: one document 1.043, half 0.280, growth seen 1.043, growth seen from half 0.280, growth to come 0.280. Versions 10–21: 0.793, 0.216, 0.216, 0.216, 0.216. Versions 22–43: 0.404, 0.481, 0.481, 0.481, 0.142. Versions 44–46: 0.127, 0.767, 0.253, 0.253, 0.034.

Before the first refit the growth seen loses 1.043 bits a symbol where the half weight loses 0.280; in the two middle stretches they tie; in the last the growth seen loses 0.253 against the half weight’s 0.767. Started from the half weight, the growth seen takes the best of both and averages 0.356 over the history, the best mean any weight a store can compute reaches here. It is still above the quarter of a bit predicted, and the gap to the weight nobody knows, 0.183, is almost all in the stretch from version 22 to 43, where every rule a store can use gives the escape one bit and the growth to come asks for two.

In the first two stretches the half weight and the growth to come give the escape the same one-bit code word and lose exactly the same, 0.280 and 0.216 bits a symbol; knowing the future buys nothing there, because a whole-bit code cannot use what it knows. Everything the oracle gains, it gains in the last two stretches, where the share still to come falls below a quarter and its code word grows to two bits and then four.

The third stretch is the longest, 22 versions, and it carries the mean. There the directory grew from 81 files to 155 in a stretch where the share of characters in added files reached 23% at most. An escape weighted at a half or at 50% of the growth seen is a code word of one bit for a set of files holding under a quarter of the characters; the old files pay for it with code space they needed.

What the escape has to name

What the escape has to name grows between refits to 68%, 46%, 23% of the characters just before each doubling, and the growth seen sets each new weight from the stretch just finished — so it is right exactly when the next stretch grows like the last, which in this directory it never didAt each version, the share of characters held in documents added since the last refit — the documents the escape names — and the escape's weight in force under three rules. Fresh share at versions 0, 10, 22, 44 and the version before each later refit: 9 68%, 21 46%, 43 23%, last 8%. by the growth seen: 5%, 71%, 50%, 27%. by the growth to come: 71%, 50%, 27%, 8%. as half the coding space: 50%, 50%, 50%, 50%.00.2500.5000.75010102244version of the directoryshare of the charactersweight: as half the coding spaceweight: by the growth seencharacters the escape namesweight: by the growth to comegrey lines: refitsweights as steps, set at each refit
Fig. 5 The share of characters in files added since the last refit, at every version, and each rule’s weight in force. Just before each refit after the first: 68% at version 9, 46% at version 21, 23% at version 43; 8% at the last version. The growth seen steps from 5% to 71%, 50% and 27%; the growth to come from 71% to 50%, 27% and 8%; half the coding space stays at 50%.

What the escape names grows from nothing at each refit to 68%, 46% and 23% of the characters just before the next, and a weight is fixed for the whole stretch. Even the growth to come is right only at the stretch’s end. For most of each stretch the escape names fewer characters than its weight assumes. That is the doubling schedule’s own cost, and no weight removes it; choosing a growth factor found the same shape in an array that doubles its memory, where the space is right only at the moment before each doubling.

The growth seen sets each new weight from the stretch just finished, the curve’s peak before the refit, rounded into a step. It is right exactly when the next stretch grows like the last. In this directory no two stretches did.

Mean, worst and last

Every weight rewrites the same 5.65 times the final array, because the schedule is the same; the weight decides only the loss, and the best a store can know, growth seen after a half-weight start, averages 0.356 bits a symbol, above the quarter of a bit predicted and below every fixed weightFor each escape weight, the mean, largest and last loss over the refitted Huffman code across the directory's 47 versions; every schedule reads 5.65 times the final array's bytes. as one document: mean 0.622, largest 1.910, last 0.250. as half the coding space: mean 0.389, largest 1.000, last 0.593. by the growth seen: mean 0.518, largest 1.910, last 0.138. growth seen, half at first: mean 0.356, largest 1.000, last 0.138. by the growth to come: mean 0.183, largest 1.000, last 0.006.00.511.52a quarter of a bitbits a symbol over the refitted Huffman code: mean (bar), largest (tick)as one document0.622as half the coding space0.389by the growth seen0.518growth seen, half at first0.356by the growth to come0.18347 versions, 20 files to 2225.65 times the final array rewritten by every schedule
Fig. 6 The mean, largest and last loss for each weight, every schedule rewriting 5.65 times the final array. One document: 0.622, 1.910, 0.250. Half the coding space: 0.389, 1.000, 0.593. Growth seen: 0.518, 1.910, 0.138. Growth seen from half: 0.356, 1.000, 0.138. Growth to come: 0.183, 1.000, 0.006.

No weight a store can compute reaches the quarter of a bit predicted; the best, the growth seen after a half-weight start, averages 0.356, and every one of them rewrites the same 5.65 times the final array. The two parts of the prediction fail for different reasons. The loss misses because the past is one refit behind on a directory whose growth slows, and because a whole-bit code word blurs every weight within a factor of two. The rewriting misses because it belongs to the schedule, refits at doublings and subtree rebuilds between, and the proposal kept that schedule.

What the measurement leaves is a small rule with a real gain: read the growth from the history, but do not trust it before there is any. Against the earlier essay’s best, 0.389 with the half weight, that is three hundredths of a bit a symbol less over the history, and 0.455 less at the last version. Against the weight nobody can know it is still twice the loss.

What the counts depend on

One directory. The history is one project’s, 47 versions, and its growth slowed at every doubling. A corpus that was not generated chose real collections for exactly this reason, and it is also this result’s limit: on a collection whose growth speeds up, the growth seen would be too small rather than too large, and the half weight would err the other way.

Refits at doublings of the file count. The schedule refits when the number of files doubles, not the number of characters, and the versions it refits at are therefore fixed by the history before any weight is chosen. On this directory the two part company as files get smaller, and a schedule keyed to characters would refit less often late in the history.

One check on the arithmetic. The plain array, a fixed number of bits for every symbol, would cost the same at every weight and every version; a saving quoted without its collection showed how a comparison against it can report a saving the rounding made. The losses here are measured against the refitted Huffman code, not the plain array, so no rounding of the plain array’s width enters them.

Bits counted, not time. The loss is in bits a symbol of the array, measured at every version and averaged with every version weighted equally, and the rewriting in bytes read. Neither the time to rebuild a subtree nor the cost of finding the added files is counted.

Still open: refitting when the escape’s code word is wrong

The schedule refits at fixed points, when the files double, and the escape’s weight is chosen at those points and held. But the store can see, at every version, how many characters its escape is naming, because the escape’s subtree is rebuilt at every version from the added files’ lengths. When that share crosses the power of two the escape’s code word assumes, the code word is wrong by a bit, and a refit then would correct it.

The measurement that follows refits whenever the share of characters behind the escape moves more than a factor of two from the share its code word stands for, with no doubling rule at all, and charges the rewriting as before. The prediction is that it refits about six times over this history instead of four, at different versions, and that its mean loss falls below a quarter of a bit for about the same rewriting, because it refits exactly where the plates show the escape’s code word going wrong, in the long third stretch. It could fail on the first stretch, where the share behind the escape climbs from nothing to two thirds in nine versions and would cross a power of two four times; a rule that refits at each crossing would rewrite the array four times for twenty files. The day a filter cannot grow rebuilt a filter from its store when its own count said its rate had passed a threshold, a clock read off the structure rather than off the calendar, and that is the kind of clock proposed here. The question is whether watching the escape is a better clock for refits than counting the files, or whether any clock that responds quickly to a young collection rewrites too often for the bits it saves.

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.

AmortisationDocument arrayDocument collectionEntropyHonest limitHuffman codingIndex sizePrediction