theory Height_Balanced_Tree imports
Cmp
Isin2 begin
text‹Height-balanced trees (HBTs) can be seen as a generalization of AVL trees. The code and the proofs were obtained by small modifications of the AVL theories. This is an implementation of sets via HBTs.›
text‹The maximal amount by which the height of two siblings may differ:›
locale HBT = fixes m :: nat assumes [arith]: "m > 0" begin
text‹Invariant:›
fun hbt :: "'a tree_ht ==> bool"where "hbt Leaf = True" | "hbt (Node l (a,n) r) = (abs(int(height l) - int(height r)) ≤ int(m) ∧ n = max (height l) (height r) + 1 ∧ hbt l ∧ hbt r)"
fun ht :: "'a tree_ht ==> nat"where "ht Leaf = 0" | "ht (Node l (a,n) r) = n"
definition node :: "'a tree_ht ==> 'a ==> 'a tree_ht ==> 'a tree_ht"where "node l a r = Node l (a, max (ht l) (ht r) + 1) r"
definition balL :: "'a tree_ht ==> 'a ==> 'a tree_ht ==> 'a tree_ht"where "balL AB b C = (if ht AB = ht C + m + 1 then case AB of Node A (a, _) B ==> if ht A ≥ ht B then node A a (node B b C) else case B of Node B🪙1 (ab, _) B🪙2 ==> node (node A a B🪙1) ab (node B🪙2 b C) else node AB b C)"
definition balR :: "'a tree_ht ==> 'a ==> 'a tree_ht ==> 'a tree_ht"where "balR A a BC = (if ht BC = ht A + m + 1 then case BC of Node B (b, _) C ==> if ht B ≤ ht C then node (node A a B) b C else case B of Node B🪙1 (ab, _) B🪙2 ==> node (node A a B🪙1) ab (node B🪙2 b C) else node A a BC)"
fun insert :: "'a::linorder ==> 'a tree_ht ==> 'a tree_ht"where "insert x Leaf = Node Leaf (x, 1) Leaf" | "insert x (Node l (a, n) r) = (case cmp x a of EQ ==> Node l (a, n) r | LT ==> balL (insert x l) a r | GT ==> balR l a (insert x r))"
fun split_max :: "'a tree_ht ==> 'a tree_ht * 'a"where "split_max (Node l (a, _) r) = (if r = Leaf then (l,a) else let (r',a') = split_max r in (balL l a r', a'))"
fun delete :: "'a::linorder ==> 'a tree_ht ==> 'a tree_ht"where "delete _ Leaf = Leaf" | "delete x (Node l (a, n) r) = (case cmp x a of EQ ==> if l = Leaf then r else let (l', a') = split_max l in balR l' a' r | LT ==> balR (delete x l) a r | GT ==> balL l a (delete x r))"
subsection‹Functional Correctness Proofs›
subsubsection "Proofs for insert"
lemma inorder_balL: "inorder (balL l a r) = inorder l @ a # inorder r" by (auto simp: node_def balL_def split:tree.splits)
lemma inorder_balR: "inorder (balR l a r) = inorder l @ a # inorder r" by (auto simp: node_def balR_def split:tree.splits)
theorem inorder_insert: "sorted(inorder t) ==> inorder(insert x t) = ins_list x (inorder t)" by (induct t)
(auto simp: ins_list_simps inorder_balL inorder_balR)
lemma ht_height[simp]: "hbt t ==> ht t = height t" by (cases t rule: tree2_cases) simp_all
text‹First, a fast but relatively manual proof with many lemmas:›
lemma height_balL: "[ hbt l; hbt r; height l = height r + m + 1 ]==> height (balL l a r) ∈ {height r + m + 1, height r + m + 2}" by (auto simp:node_def balL_def split:tree.split)
lemma height_balR: "[ hbt l; hbt r; height r = height l + m + 1 ]==> height (balR l a r) ∈ {height l + m + 1, height l + m + 2}" by(auto simp add:node_def balR_def split:tree.split)
lemma height_node[simp]: "height(node l a r) = max (height l) (height r) + 1" by (simp add: node_def)
lemma height_balL2: "[ hbt l; hbt r; height l ≠ height r + m + 1 ]==> height (balL l a r) = 1 + max (height l) (height r)" by (simp_all add: balL_def)
lemma height_balR2: "[ hbt l; hbt r; height r ≠ height l + m + 1 ]==> height (balR l a r) = 1 + max (height l) (height r)" by (simp_all add: balR_def)
lemma hbt_balL: "[ hbt l; hbt r; height r - m ≤ height l ∧ height l ≤ height r + m + 1 ]==> hbt(balL l a r)" by(auto simp: balL_def node_def max_def split!: if_splits tree.split)
lemma hbt_balR: "[ hbt l; hbt r; height l - m ≤ height r ∧ height r ≤ height l + m + 1 ]==> hbt(balR l a r)" by(auto simp: balR_def node_def max_def split!: if_splits tree.split)
theorem hbt_insert_auto: "hbt t ==> hbt(insert x t) ∧ height (insert x t) ∈ {height t, height t + 1}" apply (induction t rule: tree2_induct) (* if you want to save a few secs: apply (auto split!: if_split) *) apply (auto simp: balL_def balR_def node_def max_absorb1 max_absorb2 split!: if_split tree.split) done
theorem hbt_delete: "hbt t ==> hbt(delete x t)" "hbt t ==> height t ∈ {height (delete x t), height (delete x t) + 1}" proof (induct t rule: tree2_induct) case (Node l a n r) case 1 thus ?case using Node hbt_split_max[of l] by (auto intro!: hbt_balL hbt_balR split: prod.split) case 2 show ?case proof(cases "x = a") case True thenshow ?thesis using 1 hbt_split_max[of l] by(auto simp: balR_def max_absorb2 split!: if_splits prod.split tree.split) next case False show ?thesis proof(cases "x) case True show ?thesis proof(cases "height r = height (delete x l) + m + 1") case False with Node 1 ‹x 🚫›show ?thesis by(auto simp: balR_def) next case True hence"(height (balR (delete x l) a r) = height (delete x l) + m + 1) ∨ height (balR (delete x l) a r) = height (delete x l) + m + 2" (is"?A ∨ ?B") using Node 2height_balR[OF _ _ True] by simp thus ?thesis proof assume ?A with‹x 🚫› Node 2 show ?thesis by(auto simp: balR_def split!: if_splits) next assume ?B with‹x 🚫› Node 2 show ?thesis by(auto simp: balR_def split!: if_splits) qed qed next case False show ?thesis proof(cases "height l = height (delete x r) + m + 1") case False with Node 1 ‹¬x 🚫›‹x ≠ a›show ?thesis by(auto simp: balL_def) next case True hence"(height (balL l a (delete x r)) = height (delete x r) + m + 1) ∨ height (balL l a (delete x r)) = height (delete x r) + m + 2" (is"?A ∨ ?B") using Node 2 height_balL[OF _ _ True] by simp thus ?thesis proof assume ?A with‹¬x 🚫›‹x ≠ a› Node 2 show ?thesis by(auto simp: balL_def split: if_splits) next assume ?B with‹¬x 🚫›‹x ≠ a› Node 2 show ?thesis by(auto simp: balL_def split: if_splits) qed qed qed qed qed simp_all
text‹A more automatic proof. Complete automation as for insertion seems hard due to resource requirements.›
theorem hbt_delete_auto: "hbt t ==> hbt(delete x t)" "hbt t ==> height t ∈ {height (delete x t), height (delete x t) + 1}" proof (induct t rule: tree2_induct) case (Node l a n r) case 1 thus ?case using Node hbt_split_max[of l] by (auto intro!: hbt_balL hbt_balR split: prod.split) case 2 show ?case proof(cases "x = a") case True thus ?thesis using 2 hbt_split_max[of l] by(auto simp: balR_def max_absorb2 split!: if_splits prod.split tree.split) next case False thus ?thesis using height_balL[of l "delete x r" a] height_balR[of "delete x l" r a] 2 Node by(auto simp: balL_def balR_def split!: if_split) qed qed simp_all
subsection"Overall correctness"
interpretation S: Set_by_Ordered where empty = empty and isin = isin and insert = insert and delete = delete and inorder = inorder and inv = hbt proof (standard, goal_cases) case 1 show ?caseby (simp add: empty_def) next case 2 thus ?caseby(simp add: isin_set_inorder) next case 3 thus ?caseby(simp add: inorder_insert) next case 4 thus ?caseby(simp add: inorder_delete) next case 5 thus ?caseby (simp add: empty_def) next case 6 thus ?caseby (simp add: hbt_insert(1)) next case 7 thus ?caseby (simp add: hbt_delete(1)) qed
end
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.