Range tree
Range Tree
InductiveRange tree#✓fully proved
A one-dimensional range tree over the integers is either empty, a single leaf holding an integer, or a binary node made of two integers \(l\) and \(h\) together with a left and a right subtree. The integers \(l\) and \(h\) are meant to cache the interval \([l, h]\) spanned by the leaf values of the node's subtree; the type does not enforce this, the bounds-correctness predicate does.
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
Used by 23
DefinitionLeaf traversal of a range tree with an accumulator#✓fully proved
For a range tree \(t\) and a list \(a\) of integers, \(\operatorname{aux}(t, a)\) is \(a\) if \(t\) is empty, the list \(x\) followed by \(a\) if \(t\) is a single leaf with value \(x\), and \(\operatorname{aux}(L, \operatorname{aux}(R, a))\) if \(t\) is a node with left subtree \(L\) and right subtree \(R\).
Equivalently, \(\operatorname{aux}(t, a)\) is the leaf list of \(t\) followed by \(a\), so the leaf list is computed in linear time rather than by repeatedly appending left leaf lists.
def toListAux : RangeTree → List Int → List Int
| .empty, acc => acc
| .leaf x, acc => x :: acc
| .node _ _ left right, acc => toListAux left (toListAux right acc)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 1 · Used by 5
DefinitionLeaf list of a range tree#✓fully proved
The leaf list of a range tree \(t\) is the list of the integers stored at its leaves, read from left to right and with repetitions.
def toList (t : RangeTree) : List Int :=
toListAux t []
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
def toListAux : RangeTree → List Int → List Int
| .empty, acc => acc
| .leaf x, acc => x :: acc
| .node _ _ left right, acc => toListAux left (toListAux right acc)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:66
Uses 2 · Used by 19
TheoremRange-tree leaf traversal appends to its accumulator#✓fully proved
For every range tree \(t\) and every list \(a\) of integers, the accumulator leaf traversal of \(t\) started from \(a\) equals the leaf list of \(t\) followed by \(a\).
theorem toListAux_eq (t : RangeTree) (acc : List Int) :
toListAux t acc = t.toList ++ acc
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
def toListAux : RangeTree → List Int → List Int
| .empty, acc => acc
| .leaf x, acc => x :: acc
| .node _ _ left right, acc => toListAux left (toListAux right acc)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:66
Uses 3 · Used by 2
TheoremLeaf list of a range-tree node#✓fully proved
For all integers \(lo\), \(hi\) and range trees \(L\), \(R\), the leaf list of the node with stored bounds \(lo\), \(hi\), left subtree \(L\) and right subtree \(R\) is the leaf list of \(L\) followed by the leaf list of \(R\).
theorem toList_node (lo hi : Int) (left right : RangeTree) :
(RangeTree.node lo hi left right).toList = left.toList ++ right.toList
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 4 · Used by 5
DefinitionNumber of leaves of a range tree#✓fully proved
The size of a range tree is its number of leaves: \(0\) for the empty tree, \(1\) for a leaf, and the sum of the sizes of the two children for a node.
def size : RangeTree → Nat
| .empty => 0
| .leaf _ => 1
| .node _ _ left right => left.size + right.size
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 1 · Used by 2
TheoremLength of the leaf list of a range tree#✓fully proved
For every range tree \(t\), the list of leaf values of \(t\) read from left to right has length equal to the number of leaves of \(t\).
@[simp]
theorem length_toList (t : RangeTree) : t.toList.length = t.size
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 4 · Used by 1
DefinitionCached lower bound of a range tree#✓fully proved
For a range tree \(t\), \(\operatorname{tmin}(t)\) is \(0\) if \(t\) is empty, \(x\) if \(t\) is a single leaf with value \(x\), and the stored lower bound \(lo\) if \(t\) is a node with stored bounds \(lo\), \(hi\) and two subtrees.
The value \(0\) for the empty tree is a sentinel without meaning. Computing \(\operatorname{tmin}(t)\) takes constant time: it reads the bound cached at the root and does not traverse the tree.
def tmin : RangeTree → Int
| .empty => 0
| .leaf x => x
| .node lo _ _ _ => lo
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 1 · Used by 7
DefinitionCached upper bound of a range tree#✓fully proved
For a range tree \(t\), \(\operatorname{tmax}(t)\) is \(0\) if \(t\) is empty, \(x\) if \(t\) is a single leaf with value \(x\), and the stored upper bound \(hi\) if \(t\) is a node with stored bounds \(lo\), \(hi\) and two subtrees.
The value \(0\) for the empty tree is a sentinel without meaning.
def tmax : RangeTree → Int
| .empty => 0
| .leaf x => x
| .node _ hi _ _ => hi
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 1 · Used by 7
InductiveBounds-valid range trees#✓fully proved
For a range tree \(s\), write \(s_{\min}\) and \(s_{\max}\) for its cached lower and upper bounds: the stored interval endpoints at a node, the value itself at a leaf, and \(0\) for the empty tree. Bounds-validity is defined inductively: the empty tree and every leaf are bounds-valid, and a node with cached interval \([a, b]\), left child \(\ell\) and right child \(r\) is bounds-valid when \(\ell\) and \(r\) are bounds-valid, each of them has at least one leaf, \(a = \min(\ell_{\min}, r_{\min})\) and \(b = \max(\ell_{\max}, r_{\max})\).
The children must be nonempty because the empty tree has cached bounds \(0\): with an empty child the node cache would only enclose the leaves (a node over an empty child and the single leaf \(5\) could cache \([0, 5]\)), not equal their true interval. In a bounds-valid tree every leaf value lies in the cached interval, and if the tree has a leaf, both cached bounds are leaf values.
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 4 · Used by 10
DefinitionValid range tree#✓fully proved
A range tree \(t\) is valid when it has correct cached bounds (every node has two subtrees with nonempty leaf lists, and its stored lower and upper bounds are the minimum of the lower bounds and the maximum of the upper bounds of its two subtrees, recursively) and its leaf list is sorted in nondecreasing order.
def Valid (t : RangeTree) : Prop :=
BoundsOk t ∧ t.toList.Pairwise (· ≤ ·)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 3 · Used by 2
TheoremValid range trees have sorted leaves#✓fully proved
If a range tree \(t\) is valid, then its list of leaf values, read from left to right, is sorted in nondecreasing order.
theorem Valid.pairwise_toList {t : RangeTree} (h : Valid t) :
t.toList.Pairwise (· ≤ ·)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
def Valid (t : RangeTree) : Prop :=
BoundsOk t ∧ t.toList.Pairwise (· ≤ ·)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:144
Uses 4
TheoremLeaf values of a bounds-valid tree lie between the cached bounds#✓fully proved
Let \(t\) be a bounds-valid range tree, and write \(t_{\min}\) and \(t_{\max}\) for its cached lower and upper bounds. Then every leaf value \(x\) of \(t\) satisfies \(t_{\min} \le x \le t_{\max}\).
theorem bounds_of_mem {t : RangeTree} (hb : BoundsOk t) {x : Int}
(hx : x ∈ t.toList) :
t.tmin ≤ x ∧ x ≤ t.tmax
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 6 · Used by 1
TheoremThe cached bounds of a nonempty bounds-valid range tree are leaf values#✓fully proved
Let \(t\) be a bounds-valid range tree with at least one leaf. Then the cached lower bound of \(t\) and the cached upper bound of \(t\) are both leaf values of \(t\).
Together with the fact that every leaf value lies between the cached bounds, this shows that the cached interval is exactly the interval spanned by the leaves, not merely an enclosing one.
theorem bounds_mem_toList_of_ne_nil {t : RangeTree} (hb : BoundsOk t)
(hne : t.toList ≠ []) :
t.tmin ∈ t.toList ∧ t.tmax ∈ t.toList
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 6
DefinitionAccumulator range report#✓fully proved
For integers \(a\), \(b\) and a list \(\mathit{acc}\) of integers, the accumulator range report of a range tree for \([a, b]\) starting from \(\mathit{acc}\) is defined by recursion on the tree. The empty tree returns \(\mathit{acc}\). A leaf with value \(x\) returns \(x\) followed by \(\mathit{acc}\) if \(a \le x \le b\), and \(\mathit{acc}\) otherwise. A node with cached interval \([l, h]\) returns \(\mathit{acc}\) if \(h < a\) or \(b < l\); otherwise, if \(a \le l\) and \(h \le b\), it returns the node's leaf values from left to right followed by \(\mathit{acc}\); otherwise it returns the report of the left child starting from the report of the right child starting from \(\mathit{acc}\).
The cached bounds make each pruning test constant-time.
def reportAux : RangeTree → Int → Int → List Int → List Int
| .empty, _, _, acc => acc
| .leaf x, lo, hi, acc => if lo ≤ x ∧ x ≤ hi then x :: acc else acc
| .node nlo nhi left right, lo, hi, acc =>
if nhi < lo ∨ hi < nlo then acc
else if lo ≤ nlo ∧ nhi ≤ hi then
toListAux (.node nlo nhi left right) acc
else reportAux left lo hi (reportAux right lo hi acc)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
def toListAux : RangeTree → List Int → List Int
| .empty, acc => acc
| .leaf x, acc => x :: acc
| .node _ _ left right, acc => toListAux left (toListAux right acc)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:66
Uses 2 · Used by 3
DefinitionRange report#✓fully proved
The range report of a range tree \(t\) for integers \(a\) and \(b\) is the accumulator range report of \(t\) for \([a, b]\) starting from the empty list.
def report (t : RangeTree) (lo hi : Int) : List Int :=
reportAux t lo hi []
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
def reportAux : RangeTree → Int → Int → List Int → List Int
| .empty, _, _, acc => acc
| .leaf x, lo, hi, acc => if lo ≤ x ∧ x ≤ hi then x :: acc else acc
| .node nlo nhi left right, lo, hi, acc =>
if nhi < lo ∨ hi < nlo then acc
else if lo ≤ nlo ∧ nhi ≤ hi then
toListAux (.node nlo nhi left right) acc
else reportAux left lo hi (reportAux right lo hi acc)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:227
Uses 2 · Used by 6
TheoremAccumulator range report of a bounds-valid range tree#✓fully proved
Let \(t\) be a bounds-valid range tree, let \(a\) and \(b\) be integers and let \(\mathit{acc}\) be a list of integers. Then the accumulator range report of \(t\) for \([a, b]\) starting from \(\mathit{acc}\) is the list of the leaf values \(x\) of \(t\) with \(a \le x \le b\), in left-to-right order and with repetitions, followed by \(\mathit{acc}\).
theorem reportAux_eq_filter_append {t : RangeTree} (hb : BoundsOk t)
(lo hi : Int) (acc : List Int) :
t.reportAux lo hi acc =
t.toList.filter (fun x => lo ≤ x ∧ x ≤ hi) ++ acc
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 10 · Used by 1
TheoremCorrectness of the range report#✓fully proved
Let \(t\) be a range tree satisfying the bounds-correctness predicate: every node has two subtrees with at least one leaf each and caches the least and the greatest leaf value of its subtree. For all integers \(a\) and \(b\), the range report of \(t\) for \([a, b]\) equals the list of leaf values \(x\) of \(t\) with \(a \le x \le b\), in left-to-right order.
theorem report_eq_filter {t : RangeTree} (hb : BoundsOk t) (lo hi : Int) :
t.report lo hi = t.toList.filter (fun x => lo ≤ x ∧ x ≤ hi)
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 6 · Used by 3
TheoremMembership in a range report#✓fully proved
Let \(t\) be a range tree satisfying the bounds-correctness predicate: every node has two subtrees with at least one leaf each and caches the least and the greatest leaf value of its subtree. For all integers \(a\), \(b\) and \(x\), the value \(x\) occurs in the range report of \(t\) for \([a, b]\) if and only if \(x\) is a leaf value of \(t\) and \(a \le x \le b\).
theorem mem_report_iff {t : RangeTree} (hb : BoundsOk t) {lo hi x : Int} :
x ∈ t.report lo hi ↔ x ∈ t.toList ∧ lo ≤ x ∧ x ≤ hi
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 5 · Used by 1
DefinitionRange count#✓fully proved
For a range tree \(t\) and integers \(a\) and \(b\), the range count of \(t\) over \([a, b]\) is the length of the range report of \(t\) for \([a, b]\).
On a bounds-valid tree this is the number of leaves whose value lies in \([a, b]\).
def count (t : RangeTree) (lo hi : Int) : Nat :=
(t.report lo hi).length
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 2 · Used by 2
TheoremRange count of a bounds-valid tree#✓fully proved
Let \(t\) be a bounds-valid range tree and let \(a\) and \(b\) be integers. Then the range count of \(t\) over \([a, b]\) equals the number of leaves of \(t\) whose value lies in \([a, b]\).
theorem count_eq {t : RangeTree} (hb : BoundsOk t) (lo hi : Int) :
t.count lo hi = (t.toList.filter (fun x => lo ≤ x ∧ x ≤ hi)).length
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
Uses 6 · Used by 1
DefinitionBuilding a range tree from a list#✓fully proved
For a range tree \(s\), write \(s_{\min}\) and \(s_{\max}\) for its cached lower and upper bounds. The range tree built from a list \(L\) of integers of length \(n\) is defined by recursion on \(n\): the empty list gives the empty tree, a one-element list \([x]\) gives the leaf \(x\), and for \(n \ge 2\) it is the node whose left child \(\ell\) is the tree built from the first \(\lfloor n/2 \rfloor\) entries of \(L\), whose right child \(r\) is the tree built from the remaining entries, and whose cached interval is \([\min(\ell_{\min}, r_{\min}), \max(\ell_{\max}, r_{\max})]\).
The entries of \(L\) are kept in their given order; \(L\) is not sorted first.
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
inductive RangeTree where
| empty : RangeTree
| leaf : Int → RangeTree
| node : Int → Int → RangeTree → RangeTree → RangeTree
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:57
Uses 3 · Used by 7
TheoremBuilding a range tree preserves the list#✓fully proved
For every list \(xs\) of integers, the leaf list of the range tree built from \(xs\) is \(xs\).
@[simp]
theorem toList_build : ∀ xs : List Int, (build xs).toList = xs
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
Uses 6 · Used by 6
TheoremSize of a built range tree#✓fully proved
For every list \(\mathit{xs}\) of integers, the range tree built from \(\mathit{xs}\) has exactly as many leaves as \(\mathit{xs}\) has elements.
@[simp]
theorem size_build (xs : List Int) : (build xs).size = xs.length
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
TheoremBuilt range trees are bounds-valid#✓fully proved
For every list \(L\) of integers, the range tree built from \(L\) by recursive halving is bounds-valid.
theorem boundsOk_build : ∀ xs : List Int, BoundsOk (build xs)
inductive BoundsOk : RangeTree → Prop where
| empty : BoundsOk .empty
| leaf (x : Int) : BoundsOk (.leaf x)
| node {lo hi : Int} {left right : RangeTree} (hLeft : BoundsOk left)
(hRight : BoundsOk right) (hLeftNe : left.toList ≠ [])
(hRightNe : right.toList ≠ []) (hlo : lo = min left.tmin right.tmin)
(hhi : hi = max left.tmax right.tmax) :
BoundsOk (.node lo hi left right)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:133
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
Uses 7 · Used by 4
TheoremBuilding from a sorted list gives a valid range tree#✓fully proved
For every list \(xs\) of integers that is sorted in nondecreasing order, the range tree built from \(xs\) is valid.
Without the sortedness hypothesis the built tree still has correct cached bounds, but it need not be valid.
theorem valid_build_of_sorted {xs : List Int} (h : xs.Pairwise (· ≤ ·)) :
Valid (build xs)
def Valid (t : RangeTree) : Prop :=
BoundsOk t ∧ t.toList.Pairwise (· ≤ ·)
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:144
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
Uses 6
TheoremRange report on a built tree#✓fully proved
For every list \(\mathit{xs}\) of integers and all integers \(a\) and \(b\), the range report for \([a, b]\) on the range tree built from \(\mathit{xs}\) equals the list of elements \(x\) of \(\mathit{xs}\) with \(a \le x \le b\), in their original order.
theorem report_build (xs : List Int) (lo hi : Int) :
(build xs).report lo hi = xs.filter (fun x => lo ≤ x ∧ x ≤ hi)
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
Uses 6
TheoremRange counting on a built tree#✓fully proved
For every list \(L\) of integers and all integers \(a\) and \(b\), the range count over \([a, b]\) of the range tree built from \(L\) equals the number of entries of \(L\), counted with multiplicity, that lie in \([a, b]\).
theorem count_build (xs : List Int) (lo hi : Int) :
(build xs).count lo hi =
(xs.filter (fun x => lo ≤ x ∧ x ≤ hi)).length
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
TheoremRange report membership on a built tree#✓fully proved
For every list \(L\) of integers and all integers \(a\), \(b\) and \(x\), the value \(x\) occurs in the range report for \([a, b]\) on the range tree built from \(L\) if and only if \(x\) is an entry of \(L\) and \(a \le x \le b\).
theorem mem_report_build_iff {xs : List Int} {lo hi x : Int} :
x ∈ (build xs).report lo hi ↔ x ∈ xs ∧ lo ≤ x ∧ x ≤ hi
def build : List Int → RangeTree
| [] => .empty
| [x] => .leaf x
| xs@(_ :: _ :: _) =>
let left := build (xs.take (xs.length / 2))
let right := build (xs.drop (xs.length / 2))
.node (min left.tmin right.tmin) (max left.tmax right.tmax) left right
termination_by xs => xs.length
decreasing_by
all_goals
simp_all only [List.length_take, List.length_drop, List.length_cons]
omega
CSLibExt/Algorithms/Lean/DataStructures/RangeTree.lean:311
Uses 6
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.