diff -r 07c85c68ff03 -r 57ace76cbffa src/HOL/Data_Structures/AVL_Bal_Set.thy --- a/src/HOL/Data_Structures/AVL_Bal_Set.thy Fri May 15 08:40:28 2020 +0200 +++ b/src/HOL/Data_Structures/AVL_Bal_Set.thy Sun May 17 17:18:32 2020 +0200 @@ -1,6 +1,6 @@ -(* Tobias Nipkow *) +(* Author: Tobias Nipkow *) -section "AVL Tree with Balance Factors" +section "AVL Tree with Balance Factors (1)" theory AVL_Bal_Set imports @@ -8,6 +8,8 @@ Isin2 begin +text \This version detects height increase/decrease from above via the change in balance factors.\ + datatype bal = Lh | Bal | Rh type_synonym 'a tree_bal = "('a * bal) tree" @@ -26,13 +28,11 @@ subsection \Code\ -datatype 'a alt = Same 'a | Diff 'a - -type_synonym 'a tree_bal2 = "'a tree_bal alt" +fun is_bal where +"is_bal (Node l (a,b) r) = (b = Bal)" -fun tree :: "'a alt \ 'a" where -"tree(Same t) = t" | -"tree(Diff t) = t" +fun incr where +"incr t t' = (t = Leaf \ is_bal t \ \ is_bal t')" fun rot2 where "rot2 A a B c C = (case B of @@ -41,156 +41,131 @@ b\<^sub>2 = if bb = Lh then Rh else Bal in Node (Node A (a,b\<^sub>1) B\<^sub>1) (b,Bal) (Node B\<^sub>2 (c,b\<^sub>2) C))" -fun balL :: "'a tree_bal2 \ 'a \ bal \ 'a tree_bal \ 'a tree_bal2" where -"balL AB' c bc C = (case AB' of - Same AB \ Same (Node AB (c,bc) C) | - Diff AB \ (case bc of - Bal \ Diff (Node AB (c,Lh) C) | - Rh \ Same (Node AB (c,Bal) C) | +fun balL :: "'a tree_bal \ 'a \ bal \ 'a tree_bal \ 'a tree_bal" where +"balL AB c bc C = (case bc of + Bal \ Node AB (c,Lh) C | + Rh \ Node AB (c,Bal) C | Lh \ (case AB of - Node A (a,Lh) B \ Same(Node A (a,Bal) (Node B (c,Bal) C)) | - Node A (a,Rh) B \ Same(rot2 A a B c C))))" + Node A (a,Lh) B \ Node A (a,Bal) (Node B (c,Bal) C) | + Node A (a,Bal) B \ Node A (a,Rh) (Node B (c,Lh) C) | + Node A (a,Rh) B \ rot2 A a B c C))" -fun balR :: "'a tree_bal \ 'a \ bal \ 'a tree_bal2 \ 'a tree_bal2" where -"balR A a ba BC' = (case BC' of - Same BC \ Same (Node A (a,ba) BC) | - Diff BC \ (case ba of - Bal \ Diff (Node A (a,Rh) BC) | - Lh \ Same (Node A (a,Bal) BC) | +fun balR :: "'a tree_bal \ 'a \ bal \ 'a tree_bal \ 'a tree_bal" where +"balR A a ba BC = (case ba of + Bal \ Node A (a,Rh) BC | + Lh \ Node A (a,Bal) BC | Rh \ (case BC of - Node B (c,Rh) C \ Same(Node (Node A (a,Bal) B) (c,Bal) C) | - Node B (c,Lh) C \ Same(rot2 A a B c C))))" - -fun ins :: "'a::linorder \ 'a tree_bal \ 'a tree_bal2" where -"ins x Leaf = Diff(Node Leaf (x, Bal) Leaf)" | -"ins x (Node l (a, b) r) = (case cmp x a of - EQ \ Same(Node l (a, b) r) | - LT \ balL (ins x l) a b r | - GT \ balR l a b (ins x r))" - -definition insert :: "'a::linorder \ 'a tree_bal \ 'a tree_bal" where -"insert x t = tree(ins x t)" + Node B (c,Rh) C \ Node (Node A (a,Bal) B) (c,Bal) C | + Node B (c,Bal) C \ Node (Node A (a,Rh) B) (c,Lh) C | + Node B (c,Lh) C \ rot2 A a B c C))" -fun baldR :: "'a tree_bal \ 'a \ bal \ 'a tree_bal2 \ 'a tree_bal2" where -"baldR AB c bc C' = (case C' of - Same C \ Same (Node AB (c,bc) C) | - Diff C \ (case bc of - Bal \ Same (Node AB (c,Lh) C) | - Rh \ Diff (Node AB (c,Bal) C) | - Lh \ (case AB of - Node A (a,Lh) B \ Diff(Node A (a,Bal) (Node B (c,Bal) C)) | - Node A (a,Bal) B \ Same(Node A (a,Rh) (Node B (c,Lh) C)) | - Node A (a,Rh) B \ Diff(rot2 A a B c C))))" +fun insert :: "'a::linorder \ 'a tree_bal \ 'a tree_bal" where +"insert x Leaf = Node Leaf (x, Bal) Leaf" | +"insert x (Node l (a, b) r) = (case cmp x a of + EQ \ Node l (a, b) r | + LT \ let l' = insert x l in if incr l l' then balL l' a b r else Node l' (a,b) r | + GT \ let r' = insert x r in if incr r r' then balR l a b r' else Node l (a,b) r')" + +fun decr where +"decr t t' = (t \ Leaf \ (t' = Leaf \ \ is_bal t \ is_bal t'))" -fun baldL :: "'a tree_bal2 \ 'a \ bal \ 'a tree_bal \ 'a tree_bal2" where -"baldL A' a ba BC = (case A' of - Same A \ Same (Node A (a,ba) BC) | - Diff A \ (case ba of - Bal \ Same (Node A (a,Rh) BC) | - Lh \ Diff (Node A (a,Bal) BC) | - Rh \ (case BC of - Node B (c,Rh) C \ Diff(Node (Node A (a,Bal) B) (c,Bal) C) | - Node B (c,Bal) C \ Same(Node (Node A (a,Rh) B) (c,Lh) C) | - Node B (c,Lh) C \ Diff(rot2 A a B c C))))" - -fun split_max :: "'a tree_bal \ 'a tree_bal2 * 'a" where +fun split_max :: "'a tree_bal \ 'a tree_bal * 'a" where "split_max (Node l (a, ba) r) = - (if r = Leaf then (Diff l,a) else let (r',a') = split_max r in (baldR l a ba r', a'))" + (if r = Leaf then (l,a) + else let (r',a') = split_max r; + t' = if decr r r' then balL l a ba r' else Node l (a,ba) r' + in (t', a'))" -fun del :: "'a::linorder \ 'a tree_bal \ 'a tree_bal2" where -"del _ Leaf = Same Leaf" | -"del x (Node l (a, ba) r) = +fun delete :: "'a::linorder \ 'a tree_bal \ 'a tree_bal" where +"delete _ Leaf = Leaf" | +"delete x (Node l (a, ba) r) = (case cmp x a of - EQ \ if l = Leaf then Diff r - else let (l', a') = split_max l in baldL l' a' ba r | - LT \ baldL (del x l) a ba r | - GT \ baldR l a ba (del x r))" - -definition delete :: "'a::linorder \ 'a tree_bal \ 'a tree_bal" where -"delete x t = tree(del x t)" + EQ \ if l = Leaf then r + else let (l', a') = split_max l in + if decr l l' then balR l' a' ba r else Node l' (a',ba) r | + LT \ let l' = delete x l in if decr l l' then balR l' a ba r else Node l' (a,ba) r | + GT \ let r' = delete x r in if decr r r' then balL l a ba r' else Node l (a,ba) r')" lemmas split_max_induct = split_max.induct[case_names Node Leaf] -lemmas splits = if_splits tree.splits alt.splits bal.splits +lemmas splits = if_splits tree.splits bal.splits subsection \Proofs\ subsubsection "Proofs about insertion" -lemma avl_ins_case: "avl t \ case ins x t of - Same t' \ avl t' \ height t' = height t | - Diff t' \ avl t' \ height t' = height t + 1 \ - (\l a r. t' = Node l (a,Bal) r \ a = x \ l = Leaf \ r = Leaf)" -apply(induction x t rule: ins.induct) -apply(auto simp: max_absorb1 split!: splits) +lemma avl_insert: "avl t \ + avl(insert x t) \ + height(insert x t) = height t + (if incr t (insert x t) then 1 else 0)" +apply(induction x t rule: insert.induct) +apply(auto split!: splits) done -corollary avl_insert: "avl t \ avl(insert x t)" -using avl_ins_case[of t x] by (simp add: insert_def split: splits) +text \The following two auxiliary lemma merely simplify the proof of \inorder_insert\.\ -(* The following aux lemma simplifies the inorder_ins proof *) +lemma [simp]: "[] \ ins_list x xs" +by(cases xs) auto -lemma ins_Diff[simp]: "avl t \ - ins x t \ Diff Leaf \ - (ins x t = Diff (Node l (a,Bal) r) \ t = Leaf \ a = x \ l=Leaf \ r=Leaf) \ - ins x t \ Diff (Node l (a,Rh) Leaf) \ - ins x t \ Diff (Node Leaf (a,Lh) r)" -by(drule avl_ins_case[of _ x]) (auto split: splits) +lemma [simp]: "avl t \ insert x t \ \l, (a, Rh), \\\ \ insert x t \ \\\, (a, Lh), r\" +by(drule avl_insert[of _ x]) (auto split: splits) -theorem inorder_ins: - "\ avl t; sorted(inorder t) \ \ inorder(tree(ins x t)) = ins_list x (inorder t)" +theorem inorder_insert: + "\ avl t; sorted(inorder t) \ \ inorder(insert x t) = ins_list x (inorder t)" apply(induction t) -apply (auto simp: ins_list_simps split!: splits) +apply (auto simp: ins_list_simps Let_def split!: splits) done subsubsection "Proofs about deletion" -lemma inorder_baldL: +lemma inorder_balR: "\ ba = Rh \ r \ Leaf; avl r \ - \ inorder (tree(baldL l a ba r)) = inorder (tree l) @ a # inorder r" + \ inorder (balR l a ba r) = inorder l @ a # inorder r" by (auto split: splits) -lemma inorder_baldR: +lemma inorder_balL: "\ ba = Lh \ l \ Leaf; avl l \ - \ inorder (tree(baldR l a ba r)) = inorder l @ a # inorder (tree r)" + \ inorder (balL l a ba r) = inorder l @ a # inorder r" by (auto split: splits) +lemma height_1_iff: "avl t \ height t = Suc 0 \ (\x. t = Node Leaf (x,Bal) Leaf)" +by(cases t) (auto split: splits prod.splits) + lemma avl_split_max: - "\ split_max t = (t',a); avl t; t \ Leaf \ \ case t' of - Same t' \ avl t' \ height t = height t' | - Diff t' \ avl t' \ height t = height t' + 1" + "\ split_max t = (t',a); avl t; t \ Leaf \ \ + avl t' \ height t = height t' + (if decr t t' then 1 else 0)" apply(induction t arbitrary: t' a rule: split_max_induct) - apply(fastforce simp: max_absorb1 max_absorb2 split!: splits prod.splits) -apply simp + apply(auto simp: max_absorb1 max_absorb2 height_1_iff split!: splits prod.splits) +apply(fastforce)+ done -lemma avl_del_case: "avl t \ case del x t of - Same t' \ avl t' \ height t = height t' | - Diff t' \ avl t' \ height t = height t' + 1" -apply(induction x t rule: del.induct) - apply(auto simp: max_absorb1 max_absorb2 dest: avl_split_max split!: splits prod.splits) +lemma avl_delete: "avl t \ + avl (delete x t) \ + height t = height (delete x t) + (if decr t (delete x t) then 1 else 0)" +apply(induction x t rule: delete.induct) + apply(auto simp: max_absorb1 max_absorb2 Let_def height_1_iff dest: avl_split_max split!: splits prod.splits) done -corollary avl_delete: "avl t \ avl(delete x t)" -using avl_del_case[of t x] by(simp add: delete_def split: splits) - lemma inorder_split_maxD: "\ split_max t = (t',a); t \ Leaf; avl t \ \ - inorder (tree t') @ [a] = inorder t" + inorder t' @ [a] = inorder t" apply(induction t arbitrary: t' rule: split_max.induct) apply(fastforce split!: splits prod.splits) apply simp done -lemma neq_Leaf_if_height_neq_0[simp]: "height t \ 0 \ t \ Leaf" +lemma neq_Leaf_if_height_neq_0: "height t \ 0 \ t \ Leaf" by auto -theorem inorder_del: - "\ avl t; sorted(inorder t) \ \ inorder (tree(del x t)) = del_list x (inorder t)" +lemma split_max_Leaf: "\ t \ Leaf; avl t \ \ split_max t = (\\, x) \ t = Node Leaf (x,Bal) Leaf" +by(cases t) (auto split: splits prod.splits) + +theorem inorder_delete: + "\ avl t; sorted(inorder t) \ \ inorder (delete x t) = del_list x (inorder t)" apply(induction t rule: tree2_induct) -apply(auto simp: del_list_simps inorder_baldL inorder_baldR avl_delete inorder_split_maxD - simp del: baldR.simps baldL.simps split!: splits prod.splits) +apply(auto simp: del_list_simps inorder_balR inorder_balL avl_delete inorder_split_maxD Let_def + split_max_Leaf neq_Leaf_if_height_neq_0 + simp del: balL.simps balR.simps split!: splits prod.splits) done @@ -206,9 +181,9 @@ next case 2 thus ?case by(simp add: isin_set_inorder) next - case 3 thus ?case by(simp add: inorder_ins insert_def) + case 3 thus ?case by(simp add: inorder_insert) next - case 4 thus ?case by(simp add: inorder_del delete_def) + case 4 thus ?case by(simp add: inorder_delete) next case 5 thus ?case by (simp) next