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 trAn 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