Proofs: Persistent vector
These are the human proofs of Persistent vector, at full length.
The persistent vector keeps every version and implements an immutable dynamic array full
This proof shows: correctness.
Fix and . For let , which is 0 if and otherwise. Then is a multiple of , and when . Write for the number of leaves in the trie.
Shape. For a shift (a positive multiple of ) and a count with , the packed trie of height with leaves is the tree in which the leaf with number , for , is reached from the root by the base- digits of written with digits, most significant first, and in which an inner node exists exactly when some leaf is below it. Its slots are in use from slot 0 in each node, because leaf numbers are an initial segment . A vector is valid if its trie is the packed trie of height with leaves, each leaf full, its tail has items, and (I4) holds: , and if . Its sequence is the leaves in order of number, then the tail.
Leaf holds items to , so item is in leaf at slot , and the digits of in base are for . Since , the digit at level is the top digit, and no higher digit is lost.
Lemma 1 (no change). No procedure writes a node that existed before the call.
Proof. SET-PATH, PUSH-TAIL and POP-TAIL write only to the copy they made; NEW-PATH and NODE make new nodes; the tail is replaced by a new array in SET, PUSH and POP.
Lemma 2 (get). If is valid and , GET returns item of .
Proof. If the item is at position of the tail (L1). Otherwise L2 follows the digits of , which by the remark above reach leaf , and L3 reads slot .
Lemma 3 (set). If is valid, SET returns a valid vector whose sequence is with item replaced by .
Proof. The tail case (L4) is clear. Otherwise SET-PATH copies each node on the path to leaf , sets one child pointer of each copy to the copy below it, and changes slot of the leaf copy. The new trie has the same shape and the same leaves except that one leaf has one changed slot.
Lemma 4 (push). If is valid with items, PUSH returns a valid vector with items whose sequence is .
Proof. If (line L9), then . For , , and too: either , or and . For , means , so . So the trie is unchanged and the tail grows by one, to at most items. Otherwise the tail is full, , and , so the tail must become leaf number and the new tail is . If , the leaf number has digits, which are since is the last index of that leaf, and PUSH-TAIL (L11, L13 to L16) copies the nodes on the path that exist and makes the missing part with NEW-PATH; the result is the packed trie with leaves. Else , which is the test of line L10, and the new root of height has the old trie, which is complete, as child 0 and a path to the new leaf as child 1; its leaf numbers are , so it is the packed trie with leaves, and (I4) holds since . In the first case, (I4) holds since only grew and did not exceed .
Lemma 5 (pop). If is valid with items, POP returns a valid vector with items whose sequence is without its last item.
Proof. For the result is empty (L17). If the tail has at least two items (L18), by the computation in Lemma 4, and dropping the last tail item is right. Otherwise the tail has one item, , and when , so the last leaf, number , which holds item , becomes the tail (L19, by Lemma 2's path). POP-TAIL removes this leaf from the trie: along the path of the digits of , it keeps slots to of each node, and slot only if the subtree below still has a leaf, which happens unless every digit below is 0 (the case with ). This is the packed trie with leaves, or the empty trie. If now and the root has one child, then , and the child is the packed trie of height (L21); otherwise the root has two children and . Either way (I4) holds.
Theorem. Every version made by the operations is valid, and its sequence is the one that the abstract immutable dynamic array gives to it; GET returns the right item; and no version changes once made.
Proof. The empty vector is valid. By induction over the operations, Lemmas 3 to 5 keep validity and give the right sequences, and Lemma 2 gives the reads. By Lemma 1 no node of an existing version is written, so the sequence of each version is fixed.