Skip to content
Browse chapters
Imports

Bundled preservation for B-tree deletion

The raw node operation may leave a one-child empty root, so its root postcondition differs from the ordinary non-root invariant packet. This module proves both cases together and exposes root-normalized public results.

namespace CLRSnamespace Chapter18namespace BTree

The structural result expected from raw deletion at a node. Recursive calls return an ordinary non-root packet; the top-level call permits the single empty-root transient recorded by RootDeleteResult.

def RawDeleteResult (t : Nat) (isRoot : Bool) (tr : BTree) : Prop := if isRoot then RootDeleteResult t tr else NodeWF t false tr

An ordinary invariant packet is always an admissible raw result.

theorem rawDeleteResult_of_nodeWF {t : Nat} {isRoot : Bool} {tr : BTree} (h : NodeWF t isRoot tr) : RawDeleteResult t isRoot tr := by cases isRoot with | false => simpa [RawDeleteResult] using h | true => simp only [RawDeleteResult, ↓reduceIte] exact ⟨h.sorted, h.childBounded, h.sameDepth, Or.inl h.occupancy⟩

The leaf branch preserves all structural facts. The readiness guard is used only for a non-root leaf, where deleting one key must leave at least t - 1 keys.

theorem deleteLeaf_packet {t x : Nat} {isRoot : Bool} {ks : List Nat} (hinv : NodeWF t isRoot (node ks [])) (hready : DeleteReady t isRoot (node ks [])) : let out := node (sortedRemove x ks) [] KeysSubset out (node ks []) ∧ RawDeleteResult t isRoot out ∧ heightOf out = heightOf (node ks []) := by have hsorted : Sorted (node (sortedRemove x ks) []) := by have hkeys := hinv.sorted unfold Sorted at hkeys ⊢ exact ⟨sortedRemove_sorted x hkeys.1, by simp⟩ have hbounded : ChildBounded (node (sortedRemove x ks) []) := childBounded_node_nil _ have hdepth : SameDepth (node (sortedRemove x ks) []) := SameDepth.leaf _ have hoccupancy : Occupancy t isRoot (node (sortedRemove x ks) []) := by have hold := hinv.occupancy have hlengthLe := sortedRemove_length_le x ks have hlengthGe := sortedRemove_length_ge x ks cases isRoot with | false => have hreadyKeys : t ≤ ks.length := by simpa [DeleteReady, numKeys] using hready unfold Occupancy at hold ⊢ simp only [Bool.false_eq_true, ↓reduceIte] at hold ⊢ refine ⟨by omega, by omega, by simp, by simp⟩ | true => unfold Occupancy at hold ⊢ simp only [↓reduceIte] at hold ⊢ refine ⟨?_, by omega, by simp, by simp⟩ by_cases hempty : sortedRemove x ks = [] · simp [hempty] · have hzero : (sortedRemove x ks).length ≠ 0 := by intro hlength exact hempty (List.eq_nil_of_length_eq_zero hlength) simp [hzero] omega have hout : NodeWF t isRoot (node (sortedRemove x ks) []) := ⟨hsorted, hbounded, hoccupancy, hdepth⟩ have hsubset : KeysSubset (node (sortedRemove x ks) []) (node ks []) := by intro k hk simp only [keysOf, List.flatMap_nil, List.append_nil] at hk ⊢ exact mem_of_sortedRemove hk exact ⟨hsubset, rawDeleteResult_of_nodeWF hout, by simp [heightOf]⟩
end BTreeend Chapter18end CLRS