The other axis

Cuts that follow the gathering

Cutting an r-index's run-start values into chunks of a fixed count left chunk edges inside the places the values gather. Choosing the cuts as a shortest path through the sorted values was predicted to save a further tenth on exact copies by cutting once at each edge of the gathering. It cuts there, and saves more than a quarter: two chunks, one of them a bitmap of 664 values that a select must scan from its start. Capped at the chunk's old size, the optimum keeps the reads and saves 9% on exact copies and 15% at a divergence of 0.0005. On moderately drifted copies the uncapped optimum is smaller and cheap to read at once.

Sparse on average, dense where it gathers built the hybrid that twenty bits apart had described and never needed. The index that stores the runs keeps one suffix-array value for every run of its transform, and on a collection of drifted copies those values are few overall and crowded where the copies differ. Priced as one Elias–Fano over the whole text, they cost about nine bits each, as though they were spread evenly. Cut into chunks of a fixed number of values, each chunk held as whichever of a bitmap, its own Elias–Fano or a run is cheapest, the same set cost half as much on exact copies and a fifth less at a divergence of one character in two thousand.

No single chunk size suited every set. Thirty-two values was best on exact copies and at small divergences; at one character in five hundred, only chunks of 512 beat the single Elias–Fano at all. Even the best fixed count put chunk boundaries inside the dense places and let chunks straddle their edges. The closing section proposed choosing the cuts instead. A partition’s cost is the sum, over its chunks, of each chunk’s cheapest form plus the upper level’s charge for one more chunk, so the cheapest partition is a shortest path through the sorted values. It predicted a further 10% on exact copies, from cutting once at each edge of the dense block; 10% to 15% at 0.0005, where the gatherings vary in size; and nearly nothing on the scattered marks of an ordinary index. And it named how the prediction could fail: the cheapest partition might have very few chunks, some of them huge, which a select would have to scan.

The prediction and the named failure both came true, on the same set.

The cheapest partition as a path

Number the sorted values v0<v1<⋯<vm−1v_0 < v_1 < \dots < v_{m-1}, and give each index ii from 0 to mm a vertex. An edge from ii to jj is a chunk holding values viv_i to vj−1v_{j-1} over the positions after vi−1v_{i-1} up to vj−1v_{j-1}, and its weight is the bits of the chunk’s cheapest form plus a constant FF for its share of the upper level. A path from 0 to mm is a partition, its weight is the partition’s cost, and the shortest path is found in one pass. For each jj in order, every ii before it is tried and the cheapest arrival kept, exactly the relaxation a distance that is a path through a grid performed on an edit table. A cap on the values a chunk may hold is a window on ii, and the capped optimum is exact for its cap.

The upper level does not charge a true constant. It holds the chunks’ last values as an Elias–Fano over the whole text, whose width depends on how many chunks there are, plus a two-bit form tag and a pointer for each. So FF starts from a guess, the path is solved, the partition it finds is charged in full by the same accounting the fixed chunks received, FF is re-estimated from that partition’s real upper level, and the path is solved again. On exact copies FF moves from 28 bits to 44.5 and the partition does not change. Four rounds are run on every set, and the partition with the smallest real total is kept. Every partition is decoded back to the set it claims to hold before its size is reported, as before.

Two chunks for exact copies

On exact copies the cheapest partition of the 666 run-start values has 2 chunks where chunks of 32 make 21: one bitmap of 664 values over 2,055 positions, the copy where they gather, and the scattered rest in one moreEach row is one copy of 2,048 characters, 32 copies in all; each tick a run-start value at its text position. Shaded behind the ticks, each chunk of the cheapest partition, dark for a bitmap, pale for Elias–Fano, with a rule at every cut; the dots under the rows mark where chunks of 32 values begin. Optimal chunks, in order: 2 values over 63,481 positions as Elias–Fano; 664 values over 2,055 positions as a bitmap.bitmap chunkElias–Fano chunka chunk of 32 beginscopy 1copy 8copy 16copy 24copy 32position within the copy32 copies × 2,048 charactersexact copies
Fig. 1 The 666 run-start values of 32 exact copies, each row one copy, with the cheapest partition’s chunks shaded behind the ticks and a rule at each cut; dots mark where chunks of 32 values begin. The cheapest partition has two chunks: 2 values over 63,481 positions as Elias–Fano, and 664 values over 2,055 positions as a bitmap. Chunks of 32 make 21.

On exact copies the cheapest partition is two chunks: a bitmap of 664 values over the 2,055 positions where nearly all of them gather, and an Elias–Fano chunk holding the other two. The cuts fall at the edges of the dense block, which is what the prediction said they would do. The 21 chunks of 32 values put twenty boundaries inside that block, each paying an upper-level entry for nothing, since every one of those chunks chose the same form as its neighbours.

The block is where it is for the reason the earlier essay gave. In a collection of exact copies the 32 suffixes that begin at one offset agree until the shortest runs out, so they sort together with the last copy’s first, and nearly every run of the transform begins at a suffix of the last copy. The other thirty-one copies hold five of the 666 values between them, mostly at their ends. A bitmap of 2,055 bits holding 664 ones is about three bits a value. Elias–Fano over the same stretch would need two bits plus the logarithm of the gap, also about three bits plus its upper part, so the bitmap wins by a little, and the chunk can be as long as the block.

That partition costs 2,178 bits, 3.27 a value, against 2,983 for chunks of 32: a saving of 27%, not the 10% predicted. The prediction underestimated how much the fixed chunks were paying for their boundaries. Nineteen fewer upper-level entries at about 45 bits each are some 850 bits, about the whole difference of 805.

Uneven chunks where the copies drift

At divergence 0.0005 the cheapest partition of the 896 run-start values cuts them into 30 chunks of uneven size — 15 bitmaps over the places they gather, the largest 212 values, and Elias–Fano between — where chunks of 32 cut them into 28 regardlessEach row is one copy of 2,048 characters, 32 copies in all; each tick a run-start value at its text position. Shaded behind the ticks, each chunk of the cheapest partition, dark for a bitmap, pale for Elias–Fano, with a rule at every cut; the dots under the rows mark where chunks of 32 values begin. Optimal chunks, in order: 27 values over 12,461 positions as Elias–Fano; 11 values over 30 positions as a bitmap; 33 values over 10,734 positions as Elias–Fano; 212 values over 680 positions as a bitmap; 12 values over 767 positions as Elias–Fano; 34 values over 81 positions as a bitmap; 1 value over 1,351 positions as Elias–Fano; 25 values over 60 positions as a bitmap; 7 values over 2,125 positions as Elias–Fano; 11 values over 32 positions as a bitmap; 4 values over 4,274 positions as Elias–Fano; 19 values over 46 positions as a bitmap; 9 values over 3,770 positions as Elias–Fano; 18 values over 39 positions as a bitmap; 25 values over 3,033 positions as Elias–Fano; 40 values over 125 positions as a bitmap; 11 values over 4,772 positions as Elias–Fano; 49 values over 128 positions as a bitmap; 1 value over 192 positions as Elias–Fano; 79 values over 195 positions as a bitmap; 3 values over 365 positions as Elias–Fano; 111 values over 356 positions as a bitmap; 11 values over 3,127 positions as Elias–Fano; 13 values over 32 positions as a bitmap; 1 value over 370 positions as Elias–Fano; 39 values over 110 positions as a bitmap; 33 values over 15,747 positions as Elias–Fano; 12 values over 21 positions as a bitmap; 2 values over 386 positions as Elias–Fano; 43 values over 127 positions as a bitmap.bitmap chunkElias–Fano chunka chunk of 32 beginscopy 1copy 8copy 16copy 24copy 32position within the copy32 copies × 2,048 charactersdivergence 0.0005
Fig. 2 The 896 run-start values at divergence 0.0005, with the cheapest partition’s 30 chunks: 15 bitmaps over the places the values gather, the largest holding 212 values over 680 positions and the smallest 11 values over 30, and 15 Elias–Fano chunks between them, some holding a single value over hundreds of positions. Chunks of 32 make 28.

At a divergence of 0.0005 the cheapest partition has 30 chunks, nearly the same number as chunks of 32 make, and none of them is the same chunk. Fifteen are bitmaps laid over the places the values gather, from 11 values over 30 positions to 212 over 680. Fifteen are Elias–Fano chunks over the gaps between, and several hold a single value over hundreds of positions. The chunk count is close to the fixed partition’s by coincidence. What differs is where the boundaries are. Every cut of the optimum sits at an edge between a gathering and the sparse stretch around it, and every gathering is held whole.

A drifted copy differs from the first at a few scattered positions, and each difference starts new runs in the transform for the suffixes that run through it. So the values gather in small clusters near each difference, of different sizes depending on how many suffixes each difference separates. A fixed count can be right for one cluster size only. This partition costs 4,744 bits, 5.29 a value, against 6,073 for chunks of 32: a saving of 22%, above the 10% to 15% predicted. The prediction’s reasoning was right, since the clusters do vary in size and the optimum fits each one. Its size was low for the same reason as on exact copies: the boundaries the fixed chunks put in the wrong places were more expensive than the prediction priced them.

Under every fixed chunk at every divergence

The cheapest partition undercuts every fixed chunk at every divergence: 3.27 bits a value on exact copies against 4.48 for chunks of 32, 5.29 against 6.78 at 0.0005, and at 0.002, where no fixed chunk but 512 beats one Elias–Fano, 6.65 against its 7.86 — under the floor for an arbitrary set of that sizeBits a value for the run-start values at each divergence, held as one Elias–Fano with its select directory, as chunks of 32, at the best fixed chunk size, and as the cheapest partition with no cap; and log₂ of n choose m a value, the floor for an arbitrary set. exact copies, 666 values: Elias–Fano 9.04, chunks of 32 4.48, best fixed (32) 4.48, cheapest 3.27, floor 8.05; divergence 0.0002, 748 values: Elias–Fano 8.83, chunks of 32 5.97, best fixed (32) 5.97, cheapest 4.23, floor 7.88; divergence 0.0005, 896 values: Elias–Fano 8.56, chunks of 32 6.78, best fixed (32) 6.78, cheapest 5.29, floor 7.62; divergence 0.001, 1,034 values: Elias–Fano 8.56, chunks of 32 7.28, best fixed (32) 7.28, cheapest 6.03, floor 7.41; divergence 0.002, 1,457 values: Elias–Fano 7.86, chunks of 32 7.89, best fixed (512) 7.49, cheapest 6.65, floor 6.91; divergence 0.005, 2,377 values: Elias–Fano 7.23, chunks of 32 7.43, best fixed (512) 6.78, cheapest 6.65, floor 6.20; divergence 0.01, 4,144 values: Elias–Fano 6.53, chunks of 32 6.68, best fixed (512) 6.00, cheapest 5.92, floor 5.38.345678910divergence of the copiesbits a value00.00020.00050.0010.0020.0050.01one Elias–Fanochunks of 32best fixed chunkcheapest partitionfloor, arbitrary set32 copies × 2,048 charactersthe cheapest partition: no cap
Fig. 3 Bits a value at each divergence for one Elias–Fano with its directory, chunks of 32, the best fixed chunk, the cheapest partition with no cap, and the floor log₂ of n choose m a value. Exact copies: 9.04, 4.48, 4.48, 3.27, floor 8.05. 0.0005: 8.56, 6.78, 6.78, 5.29, 7.62. 0.002: 7.86, 7.89, 7.49 at 512, 6.65, 6.91. 0.01: 6.53, 6.68, 6.00 at 512, 5.92, 5.38.

The cheapest partition is under every fixed chunk at every divergence, and at 0.002, where chunks of 32 cost more than the single Elias–Fano, it costs 6.65 bits a value against Elias–Fano’s 7.86 and the floor’s 6.91. The fixed chunks had lost their advantage by one character in five hundred, because the clusters there are too small and too many for 32 values to fit any of them, and the larger chunks that did beat Elias–Fano did so by holding the sparse stretches too. The optimum makes 59 chunks with a median of 20 values. It is under the floor for an arbitrary set of that size, which is possible only because the set is not arbitrary, as the earlier essay’s floor plate argued. The fixed chunks never got there at this divergence.

The advantage narrows as the copies drift further. At 0.005 the optimum is 6.65 bits a value against the best fixed chunk’s 6.78, and at 0.01 it is 5.92 against 6.00, both above the floor. The clusters have merged into a spread that is nearly even, and an even spread is the case one Elias–Fano was built for; what a partition still saves there is mostly the select directory, which a chunk small enough to scan does without. Where the sparse representation loses put the crossing between Elias–Fano and a plain vector at one marked position in four; an even spread of one value in sixteen is far on Elias–Fano’s side of it, which is why a partition has little left to choose there. The prediction said the optimum would save nearly nothing on the marks. It saves 0.8% against their best fixed chunk, chunks of 512, and that is nearly nothing.

What the cheapest partition costs to read

The bits are only half the account, which every occurrence at the same price found of the sampling these values serve: a structure’s size and its cost a query move together, and quoting one of them alone settles nothing. A select asks for the jj-th value. Through one Elias–Fano it reaches a 64-bit block of the high vector by its directory and scans that block, 32.6 bits on average on every set here. Through a partition it does the same on the upper level to find the chunk, then scans the chunk: an Elias–Fano chunk’s high part up to the target one, a bitmap chunk up to the target bit, a run not at all. It is a model of the bits read, the one the earlier essay used, not a timing.

On exact copies, the cheapest partition capped at 32 values a chunk costs 4.08 bits a value for 93 bits read a select, against 4.48 and 93 for chunks of 32; with no cap it costs 3.27, and a select reads 1,065 bits, against one Elias–Fano's 33On exact copies, 666 values among 65,537: for each fixed chunk size and for the cheapest partition under each cap on the values a chunk holds, the bits a value against the mean bits a select scans after its directory lookups. One Elias–Fano: 9.04 bits a value, 32.6 read. Fixed chunks: 8: 6.52 and 41.1; 16: 5.10 and 49.0; 32: 4.48 and 92.9; 64: 4.48 and 127.3; 128: 4.91 and 231.1; 256: 5.87 and 460.6; 512: 7.68 and 1021.0. Cheapest partition: at most 32: 4.08 and 92.6, 22 chunks, the largest 32 values; at most 64: 3.68 and 116.0, 12 chunks, the largest 64 values; at most 128: 3.47 and 198.3, 7 chunks, the largest 128 values; at most 256: 3.36 and 377.7, 4 chunks, the largest 256 values; no cap: 3.27 and 1065.5, 2 chunks, the largest 664 values.4684567891011log₂ bits a select readsbits a valueone Elias–Fano832512≤32∞chunks of k valuescheapest, cappedcaps 32, 64, 128, 256, noneexact copiesa model of reads, not a timing
Fig. 4 Exact copies: bits a value against the mean bits a select reads, for fixed chunks of 8 to 512 values and for the cheapest partition capped at 32, 64, 128, 256 values a chunk and with no cap. One Elias–Fano: 9.04 and 32.6. Chunks of 32: 4.48 and 92.9. Cheapest, at most 32: 4.08 and 92.6; at most 64: 3.68 and 116; at most 256: 3.36 and 378; no cap: 3.27 and 1,065.

On exact copies the uncapped optimum’s select reads 1,065 bits, a third of its whole size and 33 times what one Elias–Fano reads. That is the failure the prediction named. A bitmap of 2,055 bits holding nearly every value is scanned from its start to the target bit, and on average that is half the bitmap. The partition that minimises space has made the set’s commonest query the slowest it has been since the plain bit vector.

The capped optimum fixes it without giving up the partition. Capped at 32 values a chunk, the cheapest partition costs 4.08 bits a value and reads 92.6 bits a select, against 4.48 and 92.9 for chunks of 32. Its chunks are the same size as before and its reads the same, but the cuts are placed rather than counted, and it is 9% smaller. Capped at 64 it is 18% smaller and reads 116 bits. The prediction’s 10% was the saving at the reads chunks of 32 already paid. The saving past that is paid for in reads, at a rate the frontier makes plain: each doubling of the cap halves what is left to save and roughly doubles the scan. From chunks of 32 upward the fixed chunks sit on a worse curve throughout, so at every read budget there is a capped optimum smaller than the fixed chunk that reads as much. Below that budget only small fixed chunks reach, 41 bits read for chunks of 8 at 6.52 bits a value, and a cap under 32 would be needed to follow them there.

At divergence 0.002, the cheapest partition capped at 32 values a chunk costs 6.79 bits a value for 61 bits read a select, against 7.89 and 70 for chunks of 32; with no cap it costs 6.65, and a select reads 83 bits, against one Elias–Fano's 33On divergence 0.002, 1,457 values among 65,537: for each fixed chunk size and for the cheapest partition under each cap on the values a chunk holds, the bits a value against the mean bits a select scans after its directory lookups. One Elias–Fano: 7.86 bits a value, 32.6 read. Fixed chunks: 8: 9.07 and 42.4; 16: 8.20 and 52.6; 32: 7.89 and 69.5; 64: 7.76 and 111.4; 128: 7.61 and 169.4; 256: 7.50 and 323.5; 512: 7.49 and 588.7. Cheapest partition: at most 32: 6.79 and 60.7, 85 chunks, the largest 32 values; at most 64: 6.66 and 77.1, 63 chunks, the largest 63 values; at most 128: 6.65 and 83.0, 59 chunks, the largest 100 values; at most 256: 6.65 and 83.0, 59 chunks, the largest 100 values; no cap: 6.65 and 83.0, 59 chunks, the largest 100 values.7894567891011log₂ bits a select readsbits a valueone Elias–Fano832512≤32∞chunks of k valuescheapest, cappedcaps 32, 64, 128, 256, nonedivergence 0.002a model of reads, not a timing
Fig. 5 Divergence 0.002: the same frontier. One Elias–Fano: 7.86 and 32.6. Chunks of 32: 7.89 and 69.5; chunks of 512: 7.49 and 589. Cheapest, at most 32: 6.79 and 60.7; at most 64: 6.66 and 77.1; at most 128, 256 or no cap: 6.65 and 83.0, 59 chunks, the largest 100 values.

At 0.002 the uncapped optimum reads 83 bits a select, less than the 589 that chunks of 512 read, and is 11% smaller than they are. No cap is needed here. The clusters at this divergence are small, the optimum’s largest chunk holds 100 values, and caps of 128 and above leave it unchanged. Capped at 32 it reads less than chunks of 32 do, 60.7 bits against 69.5, because its Elias–Fano chunks over the sparse stretches hold few values and its bitmaps over the clusters are short. The cuts that minimise space on this set are cuts a select can afford, and the closing section’s question has two answers depending on the set.

The cap is a price, set by the set

Most of what the cuts save they save under a cap that keeps the reads of chunks of 32: capped at 32 values the cheapest partition saves 9% on exact copies, 15% at 0.0005 and 14% at 0.002, and on the scattered marks 0%For each set, the bits saved by the cheapest partition against chunks of 32, as a share, under caps of 32, 64, 128 and 256 values a chunk and with none. the marks: at most 32 0%, at most 64 6%, at most 128 8%, at most 256 10%, no cap 11%; exact copies: at most 32 9%, at most 64 18%, at most 128 22%, at most 256 25%, no cap 27%; divergence 0.0002: at most 32 18%, at most 64 24%, at most 128 27%, at most 256 29%, no cap 29%; divergence 0.0005: at most 32 15%, at most 64 20%, at most 128 21%, at most 256 22%, no cap 22%; divergence 0.001: at most 32 13%, at most 64 16%, at most 128 17%, at most 256 17%, no cap 17%; divergence 0.002: at most 32 14%, at most 64 15%, at most 128 16%, at most 256 16%, no cap 16%; divergence 0.005: at most 32 6%, at most 64 9%, at most 128 10%, at most 256 11%, no cap 11%; divergence 0.01: at most 32 4%, at most 64 8%, at most 128 10%, at most 256 11%, no cap 11%.at most 32at most 64at most 128at most 256no cap0%10%20%30%the marksexact copiesdivergence 0.0002divergence 0.0005divergence 0.001divergence 0.002divergence 0.005divergence 0.01saving against chunks of 32 valuesbars left of 0%: dearer
Fig. 6 The bits saved by the cheapest partition against chunks of 32, under caps of 32, 64, 128 and 256 values and with none. Exact copies: 9%, 18%, 22%, 25%, 27%. 0.0002: 18% to 29%. 0.0005: 15%, 20%, 21%, 22%, 22%. 0.002: 14% to 16%. 0.01: 4%, 8%, 10%, 11%, 11%. The marks: 0% to 11%, all of it the larger chunks that suit a scattered set.

Capped at 32 values a chunk, the cheapest partition saves 9% on exact copies, 15% at 0.0005 and 14% at 0.002 against chunks of 32, at the same or fewer bits read. Most of the partition’s advantage on drifted copies survives the tightest cap. On exact copies most of it does not, because the advantage there was holding one gathering in one chunk, and a cap forbids exactly that.

The marks’ row needs reading with care. The saving against chunks of 32 rises to 11% with no cap, but chunks of 32 were never the right size for a scattered set. Against the marks’ best fixed chunk, 512 values, the optimum saves 0.8%, and it does so with two chunks whose select reads 1,371 bits. On a set with no gathering, there is no edge for a cut to find, and the shortest path simply prefers fewer upper-level entries, which is a reason to cap it and not a reason to use it.

How large the chunks come out

The cheapest partition sizes its chunks to the set, not to a count: on exact copies its largest chunk holds 664 of 666 values, at 0.0005 its median chunk holds 18 and its largest 212, and on the marks it makes 2 chunks of the 2,049 valuesFor each set, the cheapest partition with no cap: the number of chunks, the median and the largest number of values a chunk holds, on a logarithmic scale. the marks, 2,049 values: 2 chunks, median 1197, largest 1197; exact copies, 666 values: 2 chunks, median 664, largest 664; divergence 0.0002, 748 values: 8 chunks, median 142, largest 224; divergence 0.0005, 896 values: 30 chunks, median 18, largest 212; divergence 0.001, 1,034 values: 42 chunks, median 17, largest 117; divergence 0.002, 1,457 values: 59 chunks, median 20, largest 100; divergence 0.005, 2,377 values: 25 chunks, median 34, largest 484; divergence 0.01, 4,144 values: 15 chunks, median 112, largest 1202.1832128512204832the marks2 chunksexact copies2 chunksdivergence 0.00028 chunksdivergence 0.000530 chunksdivergence 0.00142 chunksdivergence 0.00259 chunksdivergence 0.00525 chunksdivergence 0.0115 chunksvalues a chunk: left dot the median, right dot the largestthe cheapest partition, no caplogarithmic scale
Fig. 7 The cheapest partition with no cap: number of chunks, median and largest values a chunk. Marks: 2 chunks, median and largest 1,197. Exact copies: 2, largest 664. 0.0002: 8, median 142, largest 224. 0.0005: 30, median 18, largest 212. 0.001: 42, median 17, largest 117. 0.002: 59, median 20, largest 100. 0.005: 25, median 34, largest 484. 0.01: 15, median 112, largest 1,202.

The optimum’s chunk sizes track the gatherings: one chunk of 664 values on exact copies, a median of 17 to 20 values from 0.0005 to 0.002, and at the two ends, exact copies and 0.01, a few chunks of hundreds or a thousand. It is the shape of the set read off its cheapest description. Where the values gather in a few large clusters the chunks are large, where they gather in many small ones the chunks are small, and where they stop gathering at all the cheapest description has few chunks again, because the upper level’s charge is all that varies.

That curve explains when a cap is needed. The middle divergences are where the optimum is both small and readable, since their clusters are many and short. At the two ends the cheapest partition is a handful of very large chunks and a select pays for them. It is the same trade the flat bottom of a shallow curve found in a single Elias–Fano’s width, at one level up: near the optimum the total barely moves while the parts trade places, so a constraint that moves the solution a long way costs almost nothing in bits.

What the prediction got right

The closing section predicted a further 10% on exact copies from cutting once at each edge of the dense block. The cheapest partition cuts once at each edge and saves 27%, and capped at the fixed chunk’s size it saves 9%. It predicted 10% to 15% at 0.0005; the optimum saves 22%, and 15% capped at 32. It predicted nearly nothing on the marks, and the optimum saves 0.8% against their best fixed chunk.

It named the risk precisely: a few enormous chunks that a select must scan, making the structure smaller and slower. On exact copies that happened, with a select reading 1,065 bits against Elias–Fano’s 33. At 0.0005 it happened mildly, 175 bits. At 0.001 and 0.002 it did not happen at all, since the optimum’s largest chunk was 100 to 117 values. The closing section’s question was whether the cuts that minimise space are cuts a select can afford, or whether a partition has to be priced in reads before its optimum means anything. Measured, the answer is that it has to be priced in reads, and that the price is cheap where the hybrid is most useful. The cap is one more parameter, but unlike the fixed count it does not have to be fitted to the set. A cap of 32 or 64 values is safe on every set here, and the path finds the best cuts beneath it.

What these sets do not settle

One collection. Thirty-two copies of 2,048 characters of English, drifted by independent substitutions. The collection decides which index is small found a repetition alone could reverse the order of three indexes, and the same caution applies to a partition fitted to one kind of drift. A collection whose copies differ by long insertions or by blocks moved would gather its values into fewer, larger clusters, and the optimum would make longer chunks that need the cap more.

A model of reads. The select’s cost is the bits scanned after its directory lookups. Scanning a bitmap is a word at a time with a population count, and scanning an Elias–Fano chunk’s high part is similar, so bits read are a fair proxy within one representation and a rough one across them. Nothing was timed.

The path’s charge. The upper level’s cost is approximated by a constant per chunk, re-estimated four times. A partition that was cheapest under the real, non-constant charge could in principle differ from the one found. On exact copies the estimate settled in one round and the partition did not move, and on the others the kept partition’s total is charged in full by the same accounting as the fixed chunks.

Still open: a select that starts from where it was asked

The cap exists because a select scans its chunk from the chunk’s start, and a long bitmap chunk makes that scan long. But a bitmap chunk of 2,055 bits could carry its own small directory, one count every 256 bits, eight entries of eleven bits, so that a select jumps to the right block and scans only that block. That is a second level of the same structure inside the largest chunks only, and the upper level already knows which chunks are large.

The measurement that follows gives every chunk longer than a threshold a sampled rank directory at one entry per ss bits, charges its bits in the path so that the optimum can choose to pay for it, and draws the frontier of bits against reads again, uncapped, on every set. The prediction is that on exact copies the uncapped optimum, with directories inside its one large bitmap, reads under 150 bits a select for under 3.5 bits a value, which no capped partition achieves. On the middle divergences it should change nothing, since their chunks are already short. The question is whether a cap on chunk length is the right way to buy back reads, or whether a cheapest partition should be allowed to make its chunks as long as the set wants and carry its own way into each one.

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.

Compressed bit vectorDynamic programmingElias fanoIndex sizeInformation-theoretic boundR-indexSelectSparse set