Algorithm Search⌘K

Proofs: Finger tree

These are the human proofs of Finger tree, at full length.

The finger tree operations keep the invariant and compute the right sequences full

This proof shows: correctness, termination.

We use the definitions of the page. For an element xx, items(x)\text{items}(x) is the sequence of the items below it, and for a list of elements xsxs, items(xs)\text{items}(xs) is the concatenation of their items. For a tree, seq(Empty)=⟨⟩\text{seq}(\text{Empty}) = \langle\rangle, seq(Single(x))=items(x)\text{seq}(\text{Single}(x)) = \text{items}(x) and seq(Deep(pr,m,sf))=items(pr)⋅seq(m)⋅items(sf)\text{seq}(\text{Deep}(pr, m, sf)) = \text{items}(pr) \cdot \text{seq}(m) \cdot \text{items}(sf). The depth of a tree is 0 for Empty and Single, and 1+depth(m)1 + \text{depth}(m) for Deep(pr,m,sf)\text{Deep}(pr, m, sf). A valid tree of level kk is a finger tree of level kk that satisfies (F1) to (F3). Every constructor in the pseudocode computes its cached size from its parts, so (F3) holds for every new node and tree whose parts satisfy it; we do not repeat this below. No line changes a node or tree that already exists, so every earlier version keeps its sequence, and it suffices to prove the claims for the results.

Lemma 1 (CONS). If tt is a valid tree of level kk and aa is an element of level kk, then CONS(a,t)(a, t) returns a valid tree of level kk with sequence items(a)⋅seq(t)\text{items}(a) \cdot \text{seq}(t).

Proof. By induction on the depth of tt. Lines L1 and L2 return a Single or a Deep tree with digits of one element and an empty middle, which are valid, with the right sequence. Otherwise t=Deep(pr,m,sf)t = \text{Deep}(pr, m, sf). If pr=[b,c,d,e]pr = [b, c, d, e] (line L4), then Node3(c,d,e)\text{Node3}(c, d, e) is an element of level k+1k + 1 by (F1), and mm is a valid tree of level k+1k + 1 of smaller depth, so by the hypothesis the recursive call returns a valid tree m′m' of level k+1k + 1 with seq(m′)=items(c,d,e)⋅seq(m)\text{seq}(m') = \text{items}(c, d, e) \cdot \text{seq}(m). The new prefix [a,b][a, b] has 2 elements, and the sequence is items(a,b)⋅items(c,d,e)⋅seq(m)⋅items(sf)=items(a)⋅seq(t)\text{items}(a, b) \cdot \text{items}(c, d, e) \cdot \text{seq}(m) \cdot \text{items}(sf) = \text{items}(a) \cdot \text{seq}(t). Otherwise prpr has 1 to 3 elements and line L5 makes a prefix of 2 to 4 elements. □\square

By symmetry, SNOC(t,a)(t, a) returns a valid tree with sequence seq(t)⋅items(a)\text{seq}(t) \cdot \text{items}(a). Then, by induction on the length of xsxs, CONS-ALL(xs,t)(xs, t) has sequence items(xs)⋅seq(t)\text{items}(xs) \cdot \text{seq}(t) (line L6, the last element is added first), SNOC-ALL(t,xs)(t, xs) has sequence seq(t)⋅items(xs)\text{seq}(t) \cdot \text{items}(xs) (line L7), and TREE-OF(xs)(xs) has sequence items(xs)\text{items}(xs) (line L8), all valid of the level of the elements.

Lemma 2 (VIEWL and DEEPL). Let k≥0k \ge 0.

  1. If tt is a valid tree of level kk, VIEWL(t)(t) returns nil exactly when t=Emptyt = \text{Empty}, and otherwise a pair (a,t′)(a, t') with aa an element of level kk, t′t' a valid tree of level kk, and items(a)⋅seq(t′)=seq(t)\text{items}(a) \cdot \text{seq}(t') = \text{seq}(t).
  2. If prpr is a list of 0 to 4 elements of level kk, mm a valid tree of level k+1k + 1 and sfsf a digit of level kk, DEEPL(pr,m,sf)(pr, m, sf) returns a valid tree of level kk with sequence items(pr)⋅seq(m)⋅items(sf)\text{items}(pr) \cdot \text{seq}(m) \cdot \text{items}(sf).

Proof. By induction on DD, the depth of tt in part 1 and 1+depth(m)1 + \text{depth}(m) in part 2. Part 1: lines L9 and L10 are direct. For t=Deep([a]+ ⁣ ⁣+pr,m,sf)t = \text{Deep}([a] \mathbin{+\!\!+} pr, m, sf) (line L11), prpr has 0 to 3 elements, and part 2 applies to DEEPL(pr,m,sf)(pr, m, sf) with the same value of DD, since 1+depth(m)=depth(t)1 + \text{depth}(m) = \text{depth}(t). The sequences agree by the definition of seq. Part 2: if prpr is non-empty (line L13), the Deep tree is valid. Otherwise part 1 applies to VIEWL(m)(m), with a smaller value depth(m)<D\text{depth}(m) < D. If it returns nil, mm is Empty, and line L14 returns TREE-OF(sf)(sf), with sequence items(sf)\text{items}(sf). Otherwise it returns a node nn of level k+1k + 1 and a valid tree m′m' of level k+1k + 1 with items(n)⋅seq(m′)=seq(m)\text{items}(n) \cdot \text{seq}(m') = \text{seq}(m). The children of nn are 2 or 3 elements of level kk, a valid prefix, so the tree of line L15 is valid with sequence items(n)⋅seq(m′)⋅items(sf)=seq(m)⋅items(sf)\text{items}(n) \cdot \text{seq}(m') \cdot \text{items}(sf) = \text{seq}(m) \cdot \text{items}(sf). □\square

By symmetry the same holds for VIEWR and DEEPR. In part 1 the induction measure decreases from DD to a call of part 2 with the same DD, which then calls part 1 with a smaller depth, so the recursion terminates.

Lemma 3 (NODES). If xsxs is a list of jj elements of level kk with 2≤j≤122 \le j \le 12, then NODES(xs)(xs) returns a list of ⌈j/3⌉\lceil j/3 \rceil nodes of level k+1k + 1, between 1 and 4, whose children, in order, are xsxs.

Proof. By induction on jj. Lines L16 to L18 cover j=2,3,4j = 2, 3, 4, with 1,1,21, 1, 2 nodes of 2 or 3 children, and ⌈j/3⌉\lceil j/3 \rceil is 1,1,21, 1, 2. For j≥5j \ge 5 (line L19), the rest has j−3≥2j - 3 \ge 2 elements, so the hypothesis applies, and the result has 1+⌈(j−3)/3⌉=⌈j/3⌉1 + \lceil (j - 3)/3 \rceil = \lceil j/3 \rceil nodes. For j≤12j \le 12 this is at most 4, and for j≥2j \ge 2 at least 1. The children are xsxs in order since the first node takes the first three elements. □\square

Lemma 4 (APP3). If t1t_1 and t2t_2 are valid trees of level kk and tsts is a list of 0 to 4 elements of level kk, then APP3(t1,ts,t2)(t_1, ts, t_2) returns a valid tree of level kk with sequence seq(t1)⋅items(ts)⋅seq(t2)\text{seq}(t_1) \cdot \text{items}(ts) \cdot \text{seq}(t_2).

Proof. By induction on the depth of t1t_1. Lines L20 to L23 follow from Lemma 1, its mirror image and the facts after it. In line L24 both trees are Deep. The list sf1+ ⁣ ⁣+ts+ ⁣ ⁣+pr2sf_1 \mathbin{+\!\!+} ts \mathbin{+\!\!+} pr_2 has between 1+0+1=21 + 0 + 1 = 2 and 4+4+4=124 + 4 + 4 = 12 elements of level kk, so by Lemma 3 NODES returns 1 to 4 nodes of level k+1k + 1 with the same items in order. The middles m1m_1 and m2m_2 are valid of level k+1k + 1 and m1m_1 has smaller depth than t1t_1, so by the hypothesis the recursive call returns a valid tree of level k+1k + 1 with sequence seq(m1)⋅items(sf1)⋅items(ts)⋅items(pr2)⋅seq(m2)\text{seq}(m_1) \cdot \text{items}(sf_1) \cdot \text{items}(ts) \cdot \text{items}(pr_2) \cdot \text{seq}(m_2). With the digits pr1pr_1 and sf2sf_2 around it, the result has the sequence seq(t1)⋅items(ts)⋅seq(t2)\text{seq}(t_1) \cdot \text{items}(ts) \cdot \text{seq}(t_2). □\square

With ts=[ ]ts = [\,], APPEND is correct.

Lemma 5 (LOCATE). If 0≤i<size(xs)0 \le i < \text{size}(xs), line L25 returns (k,j)(k, j) such that position ii of items(xs)\text{items}(xs) is position jj of items(xs[k])\text{items}(xs[k]), with 0≤j<size(xs[k])0 \le j < \text{size}(xs[k]).

Proof. The prefix sizes size(xs[1..k])\text{size}(xs[1 .. k]) increase with kk and reach size(xs)>i\text{size}(xs) > i, so the least kk with i<size(xs[1..k])i < \text{size}(xs[1 .. k]) exists, and size(xs[1..k−1])≤i\text{size}(xs[1 .. k - 1]) \le i by minimality. The items of xs[k]xs[k] occupy the positions from size(xs[1..k−1])\text{size}(xs[1 .. k - 1]) to size(xs[1..k])−1\text{size}(xs[1 .. k]) - 1. □\square

Lemma 6 (SPLIT-TREE). If tt is a valid non-empty tree of level kk and 0≤i<size(t)0 \le i < \text{size}(t), then SPLIT-TREE(i,t)(i, t) returns (l,x,r)(l, x, r) where ll and rr are valid trees of level kk, xx is an element of level kk, seq(l)⋅items(x)⋅seq(r)=seq(t)\text{seq}(l) \cdot \text{items}(x) \cdot \text{seq}(r) = \text{seq}(t), and size(l)≤i<size(l)+size(x)\text{size}(l) \le i < \text{size}(l) + \text{size}(x).

Proof. By induction on the depth of tt. Line L26: ll and rr are empty and 0≤i<size(x)0 \le i < \text{size}(x). Otherwise t=Deep(pr,m,sf)t = \text{Deep}(pr, m, sf).

Case i<size(pr)i < \text{size}(pr) (line L27). By Lemma 5, cutting prpr at LOCATE(i,pr)(i, pr) gives lists ll and rr of at most 3 elements and the element xx that holds position ii, with size(l)≤i<size(l)+size(x)\text{size}(l) \le i < \text{size}(l) + \text{size}(x). TREE-OF(l)(l) is valid with sequence items(l)\text{items}(l), and DEEPL(r,m,sf)(r, m, sf) is valid by Lemma 2 with sequence items(r)⋅seq(m)⋅items(sf)\text{items}(r) \cdot \text{seq}(m) \cdot \text{items}(sf). The three parts concatenate to seq(t)\text{seq}(t).

Case size(pr)≤i<size(pr)+size(m)\text{size}(pr) \le i < \text{size}(pr) + \text{size}(m) (line L28). Let i′=i−size(pr)i' = i - \text{size}(pr), so 0≤i′<size(m)0 \le i' < \text{size}(m) and mm is non-empty. By the hypothesis, SPLIT-TREE(i′,m)(i', m) returns valid trees mlml and mrmr of level k+1k + 1 and a node nn of level k+1k + 1 with seq(ml)⋅items(n)⋅seq(mr)=seq(m)\text{seq}(ml) \cdot \text{items}(n) \cdot \text{seq}(mr) = \text{seq}(m) and size(ml)≤i′<size(ml)+size(n)\text{size}(ml) \le i' < \text{size}(ml) + \text{size}(n). So 0≤i′−size(ml)<size(n)0 \le i' - \text{size}(ml) < \text{size}(n), and Lemma 5 applies to the 2 or 3 children of nn, giving lists ll and rr of at most 2 elements and an element xx of level kk. DEEPR(pr,ml,l)(pr, ml, l) and DEEPL(r,mr,sf)(r, mr, sf) are valid by Lemma 2 and its mirror image, since prpr and sfsf are digits. The sequences concatenate to items(pr)⋅seq(ml)⋅items(n)⋅seq(mr)⋅items(sf)=seq(t)\text{items}(pr) \cdot \text{seq}(ml) \cdot \text{items}(n) \cdot \text{seq}(mr) \cdot \text{items}(sf) = \text{seq}(t). The left part has size size(pr)+size(ml)+size(l)\text{size}(pr) + \text{size}(ml) + \text{size}(l), and by Lemma 5 position i′−size(ml)i' - \text{size}(ml) of items(n)\text{items}(n) lies in xx after the items of ll, which gives the position bounds.

Case i≥size(pr)+size(m)i \ge \text{size}(pr) + \text{size}(m) (line L29). Then 0≤i−size(pr)−size(m)<size(sf)0 \le i - \text{size}(pr) - \text{size}(m) < \text{size}(sf) since i<size(t)i < \text{size}(t). Note that line L29 computes i−size(m)i - \text{size}(m) after line L28 has already subtracted size(pr)\text{size}(pr). Lemma 5 on sfsf and the mirror image of Lemma 2 for DEEPR(pr,m,l)(pr, m, l) give the claim as in the first case. □\square

Corollary (SPLIT-AT). For 0<i<n0 < i < n, SPLIT-TREE(i,t)(i, t) on a valid tree of level 0 returns an item xx with size(l)≤i<size(l)+1\text{size}(l) \le i < \text{size}(l) + 1, so size(l)=i\text{size}(l) = i, and ll and CONS(x,r)(x, r) hold the first ii items and the rest. For i≤0i \le 0 and i≥ni \ge n the answer is direct.

Lemma 7 (LOOKUP). If tt is a valid tree of level 0 and 0≤i<size(t)0 \le i < \text{size}(t), LOOKUP(i,t)(i, t) returns the item at position ii of seq(t)\text{seq}(t).

Proof. Let yy be the wanted item. The loop of lines L30 and L31 keeps the invariant: tt is a valid non-empty tree and yy is at position ii of seq(t)\text{seq}(t), with 0≤i<size(t)0 \le i < \text{size}(t). When the loop condition holds, yy lies in seq(m)\text{seq}(m) at position i−size(pr)i - \text{size}(pr) by the definition of seq, and mm is non-empty, so the invariant holds for mm. The loop stops, since the depth decreases. After it, tt is a Single, or a Deep tree with i<size(pr)i < \text{size}(pr) or i≥size(pr)+size(m)i \ge \text{size}(pr) + \text{size}(m). In the first case yy is at position ii of items(x)\text{items}(x). In the second case, line L33 makes yy the item at position ii of items(pr+ ⁣ ⁣+sf)\text{items}(pr \mathbin{+\!\!+} sf): unchanged if it is in prpr, and shifted by size(m)\text{size}(m) if it is in sfsf. The loop of line L34 keeps the invariant "yy is at position ii of items(xs)\text{items}(xs), 0≤i<size(xs)0 \le i < \text{size}(xs)" by Lemma 5. Each round goes one level down, so after at most the level of the elements of xsxs rounds, xs[k]xs[k] is an item, and it is yy. □\square

Theorem. Starting from Empty, every tree built by CONS, SNOC, VIEWL, VIEWR, APPEND and SPLIT-AT, applied to any earlier trees, is a valid tree of level 0, and each operation returns the sequences that the abstract type specifies. LOOKUP returns the item at the given position. All operations terminate.

Proof. Empty is valid. Earlier trees are never changed, so they stay valid. Lemmas 1, 2, 4, 6 and 7, the corollary, and their mirror images give validity and the sequences. Each recursion is on a tree of smaller depth or a shorter list, and each loop goes down one level or along a list of at most 12 elements per round, so every call terminates. ■\blacksquare

Back to Finger tree