Algorithm Search⌘K

Proofs: Grid file

These are the human proofs of Grid file, at full length.

The grid file keeps box-shaped bucket regions that partition the grid, and its operations are correct full

This proof shows: correctness, termination.

We use the names of the pseudocode. The scales xsxs and ysys are sorted lists of distinct values, the column of xx is c(x)=∣{v∈xs:v≤x}∣c(x) = |\{v \in xs : v \le x\}| and the row of yy is r(y)=∣{v∈ys:v≤y}∣r(y) = |\{v \in ys : v \le y\}|, so column cc holds the xx with xs[c−1]≤x<xs[c]xs[c-1] \le x < xs[c], with xs[−1]=−∞xs[-1] = -\infty and xs[X−1]=+∞xs[X - 1] = +\infty. The invariant (G) asks: (1) the regions [c0,c1)×[r0,r1)[c_0, c_1) \times [r_0, r_1) of the buckets partition the cells [0,X)×[0,Y)[0, X) \times [0, Y), and G[c][r]G[c][r] is the bucket whose region holds (c,r)(c, r); (2) each point of a bucket has its cell in the region of that bucket; (3) each bucket holds at most BB points. Points are distinct.

LOOKUP. Lines L1 and L2 compute c(x)c(x) and r(y)r(y), and by part 1 line L3 returns the only bucket whose region holds the cell of pp. By part 2, if pp is stored, it is in that bucket.

Lemma 1 (split at a line). Let bb have region [c0,c1)×R[c_0, c_1) \times R with c0<a<c1c_0 < a < c_1. Replacing bb by b1b_1 with region [c0,a)×R[c_0, a) \times R and the points with x<xs[a−1]x < xs[a-1], and b2b_2 with region [a,c1)×R[a, c_1) \times R and the points with x≥xs[a−1]x \ge xs[a-1], and setting GG to b2b_2 on its region, keeps parts 1 and 2. The same holds for rows. Proof. The two regions are boxes that partition the region of bb, so part 1 holds. A point of bb has c0≤c(x)<c1c_0 \le c(x) < c_1, and c(x)≥ac(x) \ge a if and only if x≥xs[a−1]x \ge xs[a-1], so each point goes to the half whose region holds its cell. □\square

Lemma 2 (refine). Let bb have a single cell (c,r)(c, r) and at least two points with distinct xx values, and let vv be the median of their distinct xx values, v=d[⌊m/2⌋]v = d[\lfloor m/2 \rfloor] for the sorted distinct values d0<⋯<dm−1d_0 < \cdots < d_{m-1}, m≥2m \ge 2. Inserting vv into xsxs, copying column cc of GG to a new column c+1c + 1, and adding 1 to each c1>cc_1 > c and each c0>cc_0 > c keeps parts 1, 2 and 3, and then bb has columns cc and c+1c + 1, each holding at least one point of bb. Proof. All points of bb are in column cc, so xs[c−1]≤d0<v≤dm−1<xs[c]xs[c-1] \le d_0 < v \le d_{m-1} < xs[c], and vv is a new value that goes to index cc of xsxs. The old column cc becomes the columns cc, for x<vx < v, and c+1c + 1, for x≥vx \ge v, and every later column moves up by one. A region that did not contain column cc moves with its columns or stays; a region that contained it now contains both new columns. The regions are still boxes and still partition the grid, and the copied directory column names the same buckets, so part 1 holds. Each point's new cell lies in the moved region of its bucket, so part 2 holds; no bucket changes its points, so part 3 is unchanged. Finally, d0<vd_0 < v is in column cc and dm−1≥vd_{m-1} \ge v is in column c+1c + 1. The case of rows is the same. □\square

INSERT. If pp is stored, line L4 finds it by LOOKUP. Otherwise line L5 adds it to the bucket of its cell, which keeps parts 1 and 2; part 3 can fail only at that bucket. Consider a pass of the loop with bb holding k>Bk > B points, all other buckets within capacity. If the region of bb spans two or more columns or rows, lines L8 and L10 split it at a line inside its span by Lemma 1. Otherwise bb has one cell; its k≥2k \ge 2 distinct points differ on some axis, and the code refines an axis on which they differ, so by Lemma 2 line L9 keeps (G) up to part 3 at bb, and line L10 then splits bb at the new line, by Lemma 1, into two nonempty halves. After line L10, at most one of the two halves can hold more than BB points, and bb becomes the larger one. For termination, look at the pair (k,a)(k, a), with kk the number of points of bb and aa the number of cells of its region. In a pass of the first kind, if both halves get points, the larger has at most k−1k - 1 points; if all points go to one half, kk is the same and aa is smaller. In a pass of the second kind, both halves get points, so kk drops. Refining adds cells to the grid but the pair is taken for the new bb after line L10, so in every pass the pair drops in the lexicographic order, which has no infinite descending chain, since kk can drop at most kk times and between two drops aa only shrinks. Hence the loop stops, and then part 3 holds at every bucket.

DELETE. Line L12 finds the bucket of pp, and line L13 removes pp, which keeps (G). Line L14 merges uu into bb only when their regions are boxes with the same rows and adjacent columns, or the same columns and adjacent rows; their union is then a box, and the two regions are replaced by it, so part 1 holds after GG is set on the cells of uu. Each point keeps a cell in the region of its bucket, so part 2 holds, and part 3 holds by the size test. The scan of line L14 is over a finite list.

RANGE-SEARCH. Let q=(x,y)q = (x, y) be stored with lo≤q≤hilo \le q \le hi. Then c(lox)≤c(x)≤c(hix)c(lo_x) \le c(x) \le c(hi_x) and r(loy)≤r(y)≤r(hiy)r(lo_y) \le r(y) \le r(hi_y), since cc and rr do not decrease, so the cell of qq is in the block of line L15, and line L16 reads the bucket G[c(x)][r(y)]G[c(x)][r(y)], which holds qq by parts 1 and 2. Line L17 reports exactly the points of the read buckets that lie in the box, and each bucket is read once, so each point is reported once. The block is finite, so the search stops. ■\blacksquare

Back to Grid file