Algorithm Search⌘K

Proofs: Event queue

These are the human proofs of Event queue, at full length.

The event queue keeps one entry per point and pops the smallest point with all its payloads full

This proof shows: correctness.

We use the pseudocode of the page. The queue has a binary heap HH (an array with the heap order on the sweep order <<, a total order on points) and a map II from points to lists of payloads. The abstract state of the queue is a finite set SS of points and, for each p∈Sp \in S, a list A(p)A(p). The empty queue has S=∅S = \emptyset.

The abstract operations are defined as follows. INSERT(p,a)(p, a) sets S←S∪{p}S \leftarrow S \cup \{p\}; if pp was not in SS it sets A(p)←[ ]A(p) \leftarrow [\,]; then, if a≠a \ne NIL, it appends aa to A(p)A(p). POP-MIN, for S≠∅S \ne \emptyset, returns (p,A(p))(p, A(p)) with p=min⁡Sp = \min S and sets S←S∖{p}S \leftarrow S \setminus \{p\}. CONTAINS(p)(p) returns whether p∈Sp \in S, and IS-EMPTY returns whether S=∅S = \emptyset.

Invariant. The concrete state (H,I)(H, I) represents (S,A)(S, A) when:

(R1) the entries of HH are pairwise distinct, and the set of entries of HH equals the set of keys of II, which equals SS;

(R2) HH has the heap order: for each index j≥1j \ge 1, H[⌊(j−1)/2⌋]≤H[j]H[\lfloor (j-1)/2 \rfloor] \le H[j];

(R3) I[p]=A(p)I[p] = A(p) for each p∈Sp \in S.

Claim. If the queue starts empty, then after each sequence of operations (R1) to (R3) hold for the abstract state reached by the same sequence, and each operation returns the abstract result.

Proof. By induction on the number of operations.

Base. The empty queue has HH empty and II empty. Both sets are ∅=S\emptyset = S, so (R1) holds; (R2) holds with no index jj; (R3) holds with no pp.

Step. Assume (R1) to (R3) hold before an operation. We show that they hold after it, for the new abstract state, and that the result is right.

  • INSERT(p,a)(p, a), case p∈Sp \in S. By (R1), pp is a key of II, so line L1 is true. Line L2 appends aa to I[p]I[p] when a≠a \ne NIL, which is what the abstract INSERT does to A(p)A(p). HH and the set of keys of II do not change, and the abstract SS does not change, so (R1) and (R2) hold. (R3) holds for pp by the above and for the other points because nothing else changed.
  • INSERT(p,a)(p, a), case p∉Sp \notin S. By (R1), pp is not a key of II and not an entry of HH, so line L1 is false. Line L3 makes pp a key with the list [a][a], or [ ][\,] if $a = $ NIL, which is the new A(p)A(p). Line L4 adds pp to HH. The entries of HH stay pairwise distinct because pp was not one of them, and the sets of entries and of keys both become S∪{p}S \cup \{p\}, so (R1) holds. HEAP-INSERT restores the heap order (R2); this is the standard property of the sift-up of a binary heap (CLRS, Section 6.5). (R3) holds as in the first case.
  • POP-MIN, with S≠∅S \ne \emptyset. By (R1), HH is not empty. By (R2) and the transitivity of ≤\le, each entry is at least the root, because the path from the root to it is non-decreasing. So the root is min⁡\min of the entries of HH, which by (R1) is p=min⁡Sp = \min S, and line L5 returns this pp and leaves a heap of the other entries in heap order (the sift-down of CLRS, Section 6.2 and 6.5). Since the entries were distinct, pp no longer occurs in HH. Line L6 reads I[p]=A(p)I[p] = A(p) by (R3) and removes the key pp. Both sets are now S∖{p}S \setminus \{p\}, so (R1) and (R2) hold, (R3) holds for the remaining points, and line L7 returns (p,A(p))(p, A(p)) as required.
  • CONTAINS(p)(p). Line L8 returns whether pp is a key of II, which by (R1) is whether p∈Sp \in S. Nothing changes.
  • IS-EMPTY. Line L9 returns whether HH is empty, which by (R1) is whether S=∅S = \emptyset. Nothing changes.

So the invariant holds after each operation, and each result equals the abstract result. □\square

Consequence for a sweep. Let a sweep insert only points that are larger than the last popped point. Then the sequence of popped points is strictly increasing. Let qq be a popped point and q′q' the next one. Just after the pop of qq, each point of SS is larger than qq, because qq was the minimum of a set of distinct points and was removed. Each point inserted after that is larger than qq by the rule. So q′=min⁡S>qq' = \min S > q at the next pop. A popped point is then never inserted again, since each later insert is larger than it. So each event point is popped exactly once, with the payloads of all the inserts of that point. ■\blacksquare

Back to Event queue