Proofs: Self-organizing list
These are the human proofs of Self-organizing list, at full length.
Each operation of a self-organizing list keeps the invariant and returns the right result full
This proof shows: correctness, termination.
Statement. Let satisfy the invariant (I1), (I2) and, under the rule COUNT, (I3), for a map from keys to values. Then each of ACCESS, GET, PUT and DELETE stops, the invariant holds after it, and:
- ACCESS returns the node of when and nil otherwise, and the map is still ;
- GET returns when and nil otherwise, and the map is still ;
- after PUT the map is with mapped to ;
- after DELETE the map is without .
Setup. Let the nodes be in list order, with , before the operation. By (I1) this order is well defined and .
Lemma 1 (the scan of ACCESS). The loop of lines L2 and L3 stops. At its exit, either and no node has key , or is the only node with key , and , where and mean nil.
Proof. Each time line L2 tests its condition, the invariant is: for some (with meaning nil), , , and no node among has key . Line L1 makes it true with . If the test succeeds, with and , and line L3 moves the three pointers one node forward, so the invariant holds for . The number drops by exactly 1 in each round, so the loop runs at most rounds. At the exit, either , so and no node has key , or , and by (I2) is the only such node.
Lemma 2 (the move). If ACCESS finds , then after line L11 the list holds the same nodes, each once, and ends in nil. Under COUNT, the counts do not increase along the list, and the count of is 1 more than before.
Proof. Line L5 makes the predecessor of (or when ) point to , so the list from is , a list of nodes that ends in nil. Lines L6 to L10 do not change any field. They set to nil or to a node of this shorter list: under MTF ; under TRANSPOSE , a node of the shorter list or nil; under COUNT, is nil or a node reached from by line L10. Line L11 links at the front when , and else between and the node after . In both cases the list is the shorter list with put in at one place, so it holds each of the nodes once and ends in nil.
Under COUNT, let be the old count of . By (I3), the counts of are at least , and those of are at most . Line L9 sets the count of to . The loop of line L10 walks the shorter list, which has non-increasing counts, and stops at the first node with , or at nil; is the node just before , or nil if is the first node. This loop also stops: it advances one node per round along a list of nodes. Every node before the new place of has count at least , and every node after it has count at most , since the counts are non-increasing and . So the counts along the new list do not increase. The other counts do not change, so the second part of (I3) holds: the count of grows by 1 for this successful access.
ACCESS. If , Lemma 1 gives , line L4 returns nil, and nothing changes. If , Lemma 2 shows that (I1) and (I3) hold after the move. The pairs stored in the nodes do not change (only and fields change), so (I2) holds for the same map . Line L12 returns , the node of .
GET. By the result of ACCESS, line P2 returns or nil.
PUT. If ACCESS returns a node , it is the node of , and line P4 sets its value to . The keys do not change, so (I1) to (I3) still hold, and the map is with . Otherwise , and line P5 makes one new node with key , value and count 1, and adds 1 to . Line P6 or P7 links it at the front or at the end, so the list has nodes and ends in nil (I1). The keys are still distinct, since was absent, and the pairs are those of plus (I2). Under COUNT the new node is last, and its count 1 is at most every other count, which are all at least 1; its count is 1 plus its 0 accesses (I3).
DELETE. The scan of lines D1 and D2 is the scan of Lemma 1 without , so it stops at the node of or at nil. If , line D3 returns with no change. Otherwise line D4 unlinks as line L5 does, and line D5 lowers by 1. The list holds the other nodes in their old order (I1), the pairs are those of without (I2), and a sublist of a non-increasing sequence is non-increasing, with each count unchanged (I3).