Data refinement 2026-10-31
Implementation of an abstract state and operations using a more concrete representation, justified by a coupling invariant. For example, an insertion-history list may be implemented by a sorted array when clients observe only occurrence counts and order statistics. The observable behavior, rather than insertion order internally, must agree.
Keep For insertion, conceptually treat index
u[0..len) sorted, with the coupling invariantThe abstract list retains insertion order, while the concrete array retains its sorted multiset. Initially both are empty.PROCEDURE Add(x: INTEGER);
VAR i: INTEGER;
BEGIN
ASSERT(len < N);
i := len;
WHILE i > 0 DO
IF u[i-1] <= x THEN EXIT END;
u[i] := u[i-1];
i := i-1
END;
u[i] := x;
len := len+1
END Add;
PROCEDURE Get(k: INTEGER): INTEGER;
BEGIN
ASSERT((0 <= k) & (k < len));
RETURN u[k]
END Get;i as a hole. If is the old sorted prefix of length , the loop invariant is , and , with every shifted value strictly greater than . The loop variant is . The exit condition gives either no left neighbour or a left neighbour at most ; filling the hole establishes sortedness and adds exactly one occurrence, preserving the coupling invariant.When the new entry is smaller than every old entry, all old values must move in this contiguous sorted-prefix representation. Binary search can reduce comparisons to locate the insertion point, but cannot remove that linear movement cost. Appending a new largest value takes constant time in this implementation.Store the current multiset in an unsorted prefix The loop invariant is , the complete array has its original multiset, every discarded entry on the left is at most every active entry, and every active entry is at most every discarded entry on the right. Thus the desired global order statistic is the local one of rank . The two-way array partition result either identifies it or excludes the pivot and the irrelevant side. The positive loop variant strictly decreases unless the procedure returns.
a[0..len); Add appends exactly as in part (a). The coupling invariant is equality of length and multiset with abstract xs, rather than equality of insertion order. Get applies quickselect:PROCEDURE Get(k: INTEGER): INTEGER;
VAR l, r, m: INTEGER;
BEGIN
ASSERT((0 <= k) & (k < len));
l := 0; r := len;
LOOP
m := Partition(l, r);
IF k = m THEN RETURN a[m]
ELSIF k < m THEN r := m
ELSE l := m+1
END
END
END Get;Balanced pivots give , whose geometric series is . More generally, choosing a uniformly random pivot before each call, by swapping a random active entry into
a[r-1], gives expected running time on distinct keys: with constant probability, the pivot is in the middle half and the retained side has size at most . Expected work over these shrinking stages is a convergent geometric series.The particular last-entry pivot in the displayed code has no unconditional expected guarantee without an input distribution. Its worst case repeatedly discards one entry. Duplicate keys require further care: on an all-equal segment, the strict partition always returns , so selecting the last rank costs even with randomized pivot positions. A three-way array partitioning that groups all keys equal to the pivot restores the usual randomized linear expectation with duplicates; alternatively the stated expectation assumes distinct keys. This is a qualification to the bound, not to the algorithm correctness of the displayed code.