# HG changeset patch # User nipkow # Date 1467907690 -7200 # Node ID def97df48390daca8d829f9f8eb9f36346e3cdaf # Parent 9789ccc2a477724791d0cd4607976426dd32a7d0# Parent e051eea34990bf89f425f177160e75524ec6d328 merged diff -r 9789ccc2a477 -r def97df48390 CONTRIBUTORS --- a/CONTRIBUTORS Thu Jul 07 17:34:39 2016 +0200 +++ b/CONTRIBUTORS Thu Jul 07 18:08:10 2016 +0200 @@ -20,6 +20,9 @@ * June 2016: Andreas Lochbihler Formalisation of discrete subprobability distributions. +* July 2016: Daniel Stuewe + Height-size proofs in HOL/Data_Structures + Contributions to Isabelle2016 ----------------------------- diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/AA_Map.thy --- a/src/HOL/Data_Structures/AA_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/AA_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -8,7 +8,7 @@ Lookup2 begin -fun update :: "'a::cmp \ 'b \ ('a*'b) aa_tree \ ('a*'b) aa_tree" where +fun update :: "'a::linorder \ 'b \ ('a*'b) aa_tree \ ('a*'b) aa_tree" where "update x y Leaf = Node 1 Leaf (x,y) Leaf" | "update x y (Node lv t1 (a,b) t2) = (case cmp x a of @@ -16,7 +16,7 @@ GT \ split (skew (Node lv t1 (a,b) (update x y t2))) | EQ \ Node lv t1 (x,y) t2)" -fun delete :: "'a::cmp \ ('a*'b) aa_tree \ ('a*'b) aa_tree" where +fun delete :: "'a::linorder \ ('a*'b) aa_tree \ ('a*'b) aa_tree" where "delete _ Leaf = Leaf" | "delete x (Node lv l (a,b) r) = (case cmp x a of diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/AA_Set.thy --- a/src/HOL/Data_Structures/AA_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/AA_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,5 +1,5 @@ (* -Author: Tobias Nipkow and Daniel Stüwe +Author: Tobias Nipkow, Daniel Stüwe *) section \AA Tree Implementation of Sets\ @@ -36,7 +36,7 @@ hide_const (open) insert -fun insert :: "'a::cmp \ 'a aa_tree \ 'a aa_tree" where +fun insert :: "'a::linorder \ 'a aa_tree \ 'a aa_tree" where "insert x Leaf = Node 1 Leaf x Leaf" | "insert x (Node lv t1 a t2) = (case cmp x a of @@ -81,7 +81,7 @@ "del_max (Node lv l a Leaf) = (l,a)" | "del_max (Node lv l a r) = (let (r',b) = del_max r in (adjust(Node lv l a r'), b))" -fun delete :: "'a::cmp \ 'a aa_tree \ 'a aa_tree" where +fun delete :: "'a::linorder \ 'a aa_tree \ 'a aa_tree" where "delete _ Leaf = Leaf" | "delete x (Node lv l a r) = (case cmp x a of diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/AVL_Map.thy --- a/src/HOL/Data_Structures/AVL_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/AVL_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -8,14 +8,14 @@ Lookup2 begin -fun update :: "'a::cmp \ 'b \ ('a*'b) avl_tree \ ('a*'b) avl_tree" where +fun update :: "'a::linorder \ 'b \ ('a*'b) avl_tree \ ('a*'b) avl_tree" where "update x y Leaf = Node 1 Leaf (x,y) Leaf" | "update x y (Node h l (a,b) r) = (case cmp x a of EQ \ Node h l (x,y) r | LT \ balL (update x y l) (a,b) r | GT \ balR l (a,b) (update x y r))" -fun delete :: "'a::cmp \ ('a*'b) avl_tree \ ('a*'b) avl_tree" where +fun delete :: "'a::linorder \ ('a*'b) avl_tree \ ('a*'b) avl_tree" where "delete _ Leaf = Leaf" | "delete x (Node h l (a,b) r) = (case cmp x a of EQ \ del_root (Node h l (a,b) r) | diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/AVL_Set.thy --- a/src/HOL/Data_Structures/AVL_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/AVL_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,12 +1,15 @@ (* -Author: Tobias Nipkow -Derived from AFP entry AVL. +Author: Tobias Nipkow, Daniel Stüwe +Largely derived from AFP entry AVL. *) section "AVL Tree Implementation of Sets" theory AVL_Set -imports Cmp Isin2 +imports + Cmp + Isin2 + "~~/src/HOL/Number_Theory/Fib" begin type_synonym 'a avl_tree = "('a,nat) tree" @@ -48,7 +51,7 @@ else node (node l a bl) b br else node l a r)" -fun insert :: "'a::cmp \ 'a avl_tree \ 'a avl_tree" where +fun insert :: "'a::linorder \ 'a avl_tree \ 'a avl_tree" where "insert x Leaf = Node 1 Leaf x Leaf" | "insert x (Node h l a r) = (case cmp x a of EQ \ Node h l a r | @@ -68,7 +71,7 @@ lemmas del_root_cases = del_root.cases[case_names Leaf_t Node_Leaf Node_Node] -fun delete :: "'a::cmp \ 'a avl_tree \ 'a avl_tree" where +fun delete :: "'a::linorder \ 'a avl_tree \ 'a avl_tree" where "delete _ Leaf = Leaf" | "delete x (Node h l a r) = (case cmp x a of @@ -449,4 +452,83 @@ qed qed simp_all + +subsection \Height-Size Relation\ + +text \By Daniel St\"uwe\ + +fun fib_tree :: "nat \ unit avl_tree" where +"fib_tree 0 = Leaf" | +"fib_tree (Suc 0) = Node 1 Leaf () Leaf" | +"fib_tree (Suc(Suc n)) = Node (Suc(Suc(n))) (fib_tree (Suc n)) () (fib_tree n)" + +lemma [simp]: "ht (fib_tree h) = h" +by (induction h rule: "fib_tree.induct") auto + +lemma [simp]: "height (fib_tree h) = h" +by (induction h rule: "fib_tree.induct") auto + +lemma "avl(fib_tree h)" +by (induction h rule: "fib_tree.induct") auto + +lemma fib_tree_size1: "size1 (fib_tree h) = fib (h+2)" +by (induction h rule: fib_tree.induct) auto + +lemma height_invers[simp]: + "(height t = 0) = (t = Leaf)" + "avl t \ (height t = Suc h) = (\ l a r . t = Node (Suc h) l a r)" +by (induction t) auto + +lemma fib_Suc_lt: "fib n \ fib (Suc n)" +by (induction n rule: fib.induct) auto + +lemma fib_mono: "n \ m \ fib n \ fib m" +proof (induction n arbitrary: m rule: fib.induct ) + case (2 m) + thus ?case using fib_neq_0_nat[of m] by auto +next + case (3 n m) + from 3 obtain m' where "m = Suc (Suc m')" + by (metis le_Suc_ex plus_nat.simps(2)) + thus ?case using 3(1)[of "Suc m'"] 3(2)[of m'] 3(3) by auto +qed simp + +lemma size1_fib_tree_mono: + assumes "n \ m" + shows "size1 (fib_tree n) \ size1 (fib_tree m)" +using fib_tree_size1 fib_mono[OF assms] fib_mono[of "Suc n"] add_le_mono assms by fastforce + +lemma fib_tree_minimal: "avl t \ size1 (fib_tree (ht t)) \ size1 t" +proof (induction "ht t" arbitrary: t rule: fib_tree.induct) + case (2 t) + from 2 obtain l a r where "t = Node (Suc 0) l a r" by (cases t) auto + with 2 show ?case by auto +next + case (3 h t) + note [simp] = 3(3)[symmetric] + from 3 obtain l a r where [simp]: "t = Node (Suc (Suc h)) l a r" by (cases t) auto + show ?case proof (cases rule: linorder_cases[of "ht l" "ht r"]) + case equal + with 3(3,4) have ht: "ht l = Suc h" "ht r = Suc h" by auto + with 3 have "size1 (fib_tree (ht l)) \ size1 l" by auto moreover + from 3(1)[of r] 3(3,4) ht(2) have "size1 (fib_tree (ht r)) \ size1 r" by auto ultimately + show ?thesis using ht size1_fib_tree_mono[of h "Suc h"] by auto + next + case greater + with 3(3,4) have ht: "ht l = Suc h" "ht r = h" by auto + from ht 3(1,2,4) have "size1 (fib_tree (Suc h)) \ size1 l" by auto moreover + from ht 3(1,2,4) have "size1 (fib_tree h) \ size1 r" by auto ultimately + show ?thesis by auto + next + case less (* analogously *) + with 3 have ht: "ht l = h" "Suc h = ht r" by auto + from ht 3 have "size1 (fib_tree h) \ size1 l" by auto moreover + from ht 3 have "size1 (fib_tree (Suc h)) \ size1 r" by auto ultimately + show ?thesis by auto + qed +qed auto + +theorem avl_size_bound: "avl t \ fib(height t + 2) \ size1 t" +using fib_tree_minimal fib_tree_size1 by fastforce + end diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Brother12_Map.thy --- a/src/HOL/Data_Structures/Brother12_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Brother12_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -8,7 +8,7 @@ Map_by_Ordered begin -fun lookup :: "('a \ 'b) bro \ 'a::cmp \ 'b option" where +fun lookup :: "('a \ 'b) bro \ 'a::linorder \ 'b option" where "lookup N0 x = None" | "lookup (N1 t) x = lookup t x" | "lookup (N2 l (a,b) r) x = @@ -20,7 +20,7 @@ locale update = insert begin -fun upd :: "'a::cmp \ 'b \ ('a\'b) bro \ ('a\'b) bro" where +fun upd :: "'a::linorder \ 'b \ ('a\'b) bro \ ('a\'b) bro" where "upd x y N0 = L2 (x,y)" | "upd x y (N1 t) = n1 (upd x y t)" | "upd x y (N2 l (a,b) r) = @@ -29,7 +29,7 @@ EQ \ N2 l (a,y) r | GT \ n2 l (a,b) (upd x y r))" -definition update :: "'a::cmp \ 'b \ ('a\'b) bro \ ('a\'b) bro" where +definition update :: "'a::linorder \ 'b \ ('a\'b) bro \ ('a\'b) bro" where "update x y t = tree(upd x y t)" end @@ -37,7 +37,7 @@ context delete begin -fun del :: "'a::cmp \ ('a\'b) bro \ ('a\'b) bro" where +fun del :: "'a::linorder \ ('a\'b) bro \ ('a\'b) bro" where "del _ N0 = N0" | "del x (N1 t) = N1 (del x t)" | "del x (N2 l (a,b) r) = @@ -48,7 +48,7 @@ None \ N1 l | Some (ab, r') \ n2 l ab r'))" -definition delete :: "'a::cmp \ ('a\'b) bro \ ('a\'b) bro" where +definition delete :: "'a::linorder \ ('a\'b) bro \ ('a\'b) bro" where "delete a t = tree (del a t)" end @@ -180,7 +180,7 @@ show ?thesis by simp qed qed - } ultimately show ?case by auto + } ultimately show ?case by auto } { case 2 with Suc.IH(1) show ?case by auto } qed auto diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Brother12_Set.thy --- a/src/HOL/Data_Structures/Brother12_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Brother12_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,4 +1,4 @@ -(* Author: Tobias Nipkow *) +(* Author: Tobias Nipkow, Daniel Stüwe *) section \1-2 Brother Tree Implementation of Sets\ @@ -6,6 +6,7 @@ imports Cmp Set_by_Ordered + "~~/src/HOL/Number_Theory/Fib" begin subsection \Data Type and Operations\ @@ -25,7 +26,7 @@ "inorder (L2 a) = [a]" | "inorder (N3 t1 a1 t2 a2 t3) = inorder t1 @ a1 # inorder t2 @ a2 # inorder t3" -fun isin :: "'a bro \ 'a::cmp \ bool" where +fun isin :: "'a bro \ 'a::linorder \ bool" where "isin N0 x = False" | "isin (N1 t) x = isin t x" | "isin (N2 l a r) x = @@ -53,7 +54,7 @@ "n2 t1 a1 (N3 t2 a2 t3 a3 t4) = N3 t1 a1 (N1 t2) a2 (N2 t3 a3 t4)" | "n2 t1 a t2 = N2 t1 a t2" -fun ins :: "'a::cmp \ 'a bro \ 'a bro" where +fun ins :: "'a::linorder \ 'a bro \ 'a bro" where "ins x N0 = L2 x" | "ins x (N1 t) = n1 (ins x t)" | "ins x (N2 l a r) = @@ -67,7 +68,7 @@ "tree (N3 t1 a1 t2 a2 t3) = N2 (N2 t1 a1 t2) a2 (N1 t3)" | "tree t = t" -definition insert :: "'a::cmp \ 'a bro \ 'a bro" where +definition insert :: "'a::linorder \ 'a bro \ 'a bro" where "insert x t = tree(ins x t)" end @@ -102,7 +103,7 @@ None \ Some (a, N1 t2) | Some (b, t1') \ Some (b, n2 t1' a t2))" -fun del :: "'a::cmp \ 'a bro \ 'a bro" where +fun del :: "'a::linorder \ 'a bro \ 'a bro" where "del _ N0 = N0" | "del x (N1 t) = N1 (del x t)" | "del x (N2 l a r) = @@ -117,7 +118,7 @@ "tree (N1 t) = t" | "tree t = t" -definition delete :: "'a::cmp \ 'a bro \ 'a bro" where +definition delete :: "'a::linorder \ 'a bro \ 'a bro" where "delete a t = tree (del a t)" end @@ -483,4 +484,68 @@ case 7 thus ?case using delete.delete_type by blast qed auto + +subsection \Height-Size Relation\ + +text \By Daniel St\"uwe\ + +fun fib_tree :: "nat \ unit bro" where + "fib_tree 0 = N0" +| "fib_tree (Suc 0) = N2 N0 () N0" +| "fib_tree (Suc(Suc h)) = N2 (fib_tree (h+1)) () (N1 (fib_tree h))" + +fun fib' :: "nat \ nat" where + "fib' 0 = 0" +| "fib' (Suc 0) = 1" +| "fib' (Suc(Suc h)) = 1 + fib' (Suc h) + fib' h" + +fun size :: "'a bro \ nat" where + "size N0 = 0" +| "size (N1 t) = size t" +| "size (N2 t1 _ t2) = 1 + size t1 + size t2" + +lemma fib_tree_B: "fib_tree h \ B h" +by (induction h rule: fib_tree.induct) auto + +declare [[names_short]] + +lemma size_fib': "size (fib_tree h) = fib' h" +by (induction h rule: fib_tree.induct) auto + +lemma fibfib: "fib' h + 1 = fib (Suc(Suc h))" +by (induction h rule: fib_tree.induct) auto + +lemma B_N2_cases[consumes 1]: +assumes "N2 t1 a t2 \ B (Suc n)" +obtains + (BB) "t1 \ B n" and "t2 \ B n" | + (UB) "t1 \ U n" and "t2 \ B n" | + (BU) "t1 \ B n" and "t2 \ U n" +using assms by auto + +lemma size_bounded: "t \ B h \ size t \ size (fib_tree h)" +unfolding size_fib' proof (induction h arbitrary: t rule: fib'.induct) +case (3 h t') + note main = 3 + then obtain t1 a t2 where t': "t' = N2 t1 a t2" by auto + with main have "N2 t1 a t2 \ B (Suc (Suc h))" by auto + thus ?case proof (cases rule: B_N2_cases) + case BB + then obtain x y z where t2: "t2 = N2 x y z \ t2 = N2 z y x" "x \ B h" by auto + show ?thesis unfolding t' using main(1)[OF BB(1)] main(2)[OF t2(2)] t2(1) by auto + next + case UB + then obtain t11 where t1: "t1 = N1 t11" "t11 \ B h" by auto + show ?thesis unfolding t' t1(1) using main(2)[OF t1(2)] main(1)[OF UB(2)] by simp + next + case BU + then obtain t22 where t2: "t2 = N1 t22" "t22 \ B h" by auto + show ?thesis unfolding t' t2(1) using main(2)[OF t2(2)] main(1)[OF BU(1)] by simp + qed +qed auto + +theorem "t \ B h \ fib (h + 2) \ size t + 1" +using size_bounded +by (simp add: size_fib' fibfib[symmetric] del: fib.simps) + end diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Cmp.thy --- a/src/HOL/Data_Structures/Cmp.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Cmp.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,4 +1,4 @@ -(* Author: Tobias Nipkow *) +(* Author: Tobias Nipkow, Daniel Stüwe *) section {* Three-Way Comparison *} @@ -6,16 +6,23 @@ imports Main begin -datatype cmp = LT | EQ | GT +datatype cmp_val = LT | EQ | GT -class cmp = linorder + -fixes cmp :: "'a \ 'a \ cmp" -assumes LT[simp]: "cmp x y = LT \ x < y" -assumes EQ[simp]: "cmp x y = EQ \ x = y" -assumes GT[simp]: "cmp x y = GT \ x > y" +function cmp :: "'a:: linorder \ 'a \ cmp_val" where +"x < y \ cmp x y = LT" | +"x = y \ cmp x y = EQ" | +"x > y \ cmp x y = GT" +by (auto, force) +termination by lexicographic_order + +lemma + LT[simp]: "cmp x y = LT \ x < y" +and EQ[simp]: "cmp x y = EQ \ x = y" +and GT[simp]: "cmp x y = GT \ x > y" +by (cases x y rule: linorder_cases, auto)+ lemma case_cmp_if[simp]: "(case c of EQ \ e | LT \ l | GT \ g) = (if c = LT then l else if c = GT then g else e)" -by(simp split: cmp.split) +by(simp split: cmp_val.split) end diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Isin2.thy --- a/src/HOL/Data_Structures/Isin2.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Isin2.thy Thu Jul 07 18:08:10 2016 +0200 @@ -9,7 +9,7 @@ Set_by_Ordered begin -fun isin :: "('a::cmp,'b) tree \ 'a \ bool" where +fun isin :: "('a::linorder,'b) tree \ 'a \ bool" where "isin Leaf x = False" | "isin (Node _ l a r) x = (case cmp x a of diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Lookup2.thy --- a/src/HOL/Data_Structures/Lookup2.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Lookup2.thy Thu Jul 07 18:08:10 2016 +0200 @@ -9,7 +9,7 @@ Map_by_Ordered begin -fun lookup :: "('a::cmp * 'b, 'c) tree \ 'a \ 'b option" where +fun lookup :: "('a::linorder * 'b, 'c) tree \ 'a \ 'b option" where "lookup Leaf x = None" | "lookup (Node _ l (a,b) r) x = (case cmp x a of LT \ lookup l x | GT \ lookup r x | EQ \ Some b)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/RBT_Map.thy --- a/src/HOL/Data_Structures/RBT_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/RBT_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -8,7 +8,7 @@ Lookup2 begin -fun upd :: "'a::cmp \ 'b \ ('a*'b) rbt \ ('a*'b) rbt" where +fun upd :: "'a::linorder \ 'b \ ('a*'b) rbt \ ('a*'b) rbt" where "upd x y Leaf = R Leaf (x,y) Leaf" | "upd x y (B l (a,b) r) = (case cmp x a of LT \ bal (upd x y l) (a,b) r | @@ -19,12 +19,12 @@ GT \ R l (a,b) (upd x y r) | EQ \ R l (x,y) r)" -definition update :: "'a::cmp \ 'b \ ('a*'b) rbt \ ('a*'b) rbt" where +definition update :: "'a::linorder \ 'b \ ('a*'b) rbt \ ('a*'b) rbt" where "update x y t = paint Black (upd x y t)" -fun del :: "'a::cmp \ ('a*'b)rbt \ ('a*'b)rbt" -and delL :: "'a::cmp \ ('a*'b)rbt \ 'a*'b \ ('a*'b)rbt \ ('a*'b)rbt" -and delR :: "'a::cmp \ ('a*'b)rbt \ 'a*'b \ ('a*'b)rbt \ ('a*'b)rbt" +fun del :: "'a::linorder \ ('a*'b)rbt \ ('a*'b)rbt" +and delL :: "'a::linorder \ ('a*'b)rbt \ 'a*'b \ ('a*'b)rbt \ ('a*'b)rbt" +and delR :: "'a::linorder \ ('a*'b)rbt \ 'a*'b \ ('a*'b)rbt \ ('a*'b)rbt" where "del x Leaf = Leaf" | "del x (Node c t1 (a,b) t2) = (case cmp x a of @@ -36,7 +36,7 @@ "delR x t1 a (B t2 b t3) = balR t1 a (del x (B t2 b t3))" | "delR x t1 a t2 = R t1 a (del x t2)" -definition delete :: "'a::cmp \ ('a*'b) rbt \ ('a*'b) rbt" where +definition delete :: "'a::linorder \ ('a*'b) rbt \ ('a*'b) rbt" where "delete x t = paint Black (del x t)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/RBT_Set.thy --- a/src/HOL/Data_Structures/RBT_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/RBT_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,4 +1,4 @@ -(* Author: Tobias Nipkow *) +(* Author: Tobias Nipkow, Daniel Stüwe *) section \Red-Black Tree Implementation of Sets\ @@ -9,7 +9,7 @@ Isin2 begin -fun ins :: "'a::cmp \ 'a rbt \ 'a rbt" where +fun ins :: "'a::linorder \ 'a rbt \ 'a rbt" where "ins x Leaf = R Leaf x Leaf" | "ins x (B l a r) = (case cmp x a of @@ -22,12 +22,12 @@ GT \ R l a (ins x r) | EQ \ R l a r)" -definition insert :: "'a::cmp \ 'a rbt \ 'a rbt" where +definition insert :: "'a::linorder \ 'a rbt \ 'a rbt" where "insert x t = paint Black (ins x t)" -fun del :: "'a::cmp \ 'a rbt \ 'a rbt" -and delL :: "'a::cmp \ 'a rbt \ 'a \ 'a rbt \ 'a rbt" -and delR :: "'a::cmp \ 'a rbt \ 'a \ 'a rbt \ 'a rbt" +fun del :: "'a::linorder \ 'a rbt \ 'a rbt" +and delL :: "'a::linorder \ 'a rbt \ 'a \ 'a rbt \ 'a rbt" +and delR :: "'a::linorder \ 'a rbt \ 'a \ 'a rbt \ 'a rbt" where "del x Leaf = Leaf" | "del x (Node _ l a r) = @@ -40,7 +40,7 @@ "delR x t1 a (B t2 b t3) = balR t1 a (del x (B t2 b t3))" | "delR x l a r = R l a (del x r)" -definition delete :: "'a::cmp \ 'a rbt \ 'a rbt" where +definition delete :: "'a::linorder \ 'a rbt \ 'a rbt" where "delete x t = paint Black (del x t)" @@ -88,21 +88,9 @@ by (auto simp: delete_def inorder_del inorder_paint) -interpretation Set_by_Ordered -where empty = Leaf and isin = isin and insert = insert and delete = delete -and inorder = inorder and inv = "\_. True" -proof (standard, goal_cases) - case 1 show ?case by simp -next - case 2 thus ?case by(simp add: isin_set) -next - case 3 thus ?case by(simp add: inorder_insert) -next - case 4 thus ?case by(simp add: inorder_delete) -qed auto +subsection \Structural invariants\ - -subsection \Structural invariants\ +text\The proofs are due to Markus Reiter and Alexander Krauss,\ fun color :: "'a rbt \ color" where "color Leaf = Black" | @@ -112,24 +100,24 @@ "bheight Leaf = 0" | "bheight (Node c l x r) = (if c = Black then Suc(bheight l) else bheight l)" -fun inv1 :: "'a rbt \ bool" where -"inv1 Leaf = True" | -"inv1 (Node c l a r) = - (inv1 l \ inv1 r \ (c = Black \ color l = Black \ color r = Black))" +fun invc :: "'a rbt \ bool" where +"invc Leaf = True" | +"invc (Node c l a r) = + (invc l \ invc r \ (c = Black \ color l = Black \ color r = Black))" -fun inv1_root :: "'a rbt \ bool" \ \Weaker version\ where -"inv1_root Leaf = True" | -"inv1_root (Node c l a r) = (inv1 l \ inv1 r)" +fun invc_sons :: "'a rbt \ bool" \ \Weaker version\ where +"invc_sons Leaf = True" | +"invc_sons (Node c l a r) = (invc l \ invc r)" -fun inv2 :: "'a rbt \ bool" where -"inv2 Leaf = True" | -"inv2 (Node c l x r) = (inv2 l \ inv2 r \ bheight l = bheight r)" +fun invh :: "'a rbt \ bool" where +"invh Leaf = True" | +"invh (Node c l x r) = (invh l \ invh r \ bheight l = bheight r)" -lemma inv1_rootI[simp]: "inv1 t \ inv1_root t" +lemma invc_sonsI: "invc t \ invc_sons t" by (cases t) simp+ definition rbt :: "'a rbt \ bool" where -"rbt t = (inv1 t \ inv2 t \ color t = Black)" +"rbt t = (invc t \ invh t \ color t = Black)" lemma color_paint_Black: "color (paint Black t) = Black" by (cases t) auto @@ -137,142 +125,386 @@ theorem rbt_Leaf: "rbt Leaf" by (simp add: rbt_def) -lemma paint_inv1_root: "inv1_root t \ inv1_root (paint c t)" +lemma paint_invc_sons: "invc_sons t \ invc_sons (paint c t)" by (cases t) auto -lemma inv1_paint_Black: "inv1_root t \ inv1 (paint Black t)" +lemma invc_paint_Black: "invc_sons t \ invc (paint Black t)" by (cases t) auto -lemma inv2_paint: "inv2 t \ inv2 (paint c t)" +lemma invh_paint: "invh t \ invh (paint c t)" by (cases t) auto -lemma inv1_bal: "\inv1_root l; inv1_root r\ \ inv1 (bal l a r)" +lemma invc_bal: "\invc_sons l; invc_sons r\ \ invc (bal l a r)" by (induct l a r rule: bal.induct) auto lemma bheight_bal: "bheight l = bheight r \ bheight (bal l a r) = Suc (bheight l)" by (induct l a r rule: bal.induct) auto -lemma inv2_bal: - "\ inv2 l; inv2 r; bheight l = bheight r \ \ inv2 (bal l a r)" +lemma invh_bal: + "\ invh l; invh r; bheight l = bheight r \ \ invh (bal l a r)" by (induct l a r rule: bal.induct) auto subsubsection \Insertion\ -lemma inv1_ins: assumes "inv1 t" - shows "color t = Black \ inv1 (ins x t)" "inv1_root (ins x t)" +lemma invc_ins: assumes "invc t" + shows "color t = Black \ invc (ins x t)" "invc_sons (ins x t)" using assms -by (induct x t rule: ins.induct) (auto simp: inv1_bal) +by (induct x t rule: ins.induct) (auto simp: invc_bal invc_sonsI) -lemma inv2_ins: assumes "inv2 t" - shows "inv2 (ins x t)" "bheight (ins x t) = bheight t" +lemma invh_ins: assumes "invh t" + shows "invh (ins x t)" "bheight (ins x t) = bheight t" using assms -by (induct x t rule: ins.induct) (auto simp: inv2_bal bheight_bal) +by (induct x t rule: ins.induct) (auto simp: invh_bal bheight_bal) -theorem rbt_ins: "rbt t \ rbt (insert x t)" -by (simp add: inv1_ins inv2_ins color_paint_Black inv1_paint_Black inv2_paint +theorem rbt_insert: "rbt t \ rbt (insert x t)" +by (simp add: invc_ins invh_ins color_paint_Black invc_paint_Black invh_paint rbt_def insert_def) -(* -lemma bheight_paintR'[simp]: "color t = Black \ bheight (paint Red t) = bheight t - 1" + +subsubsection \Deletion\ + +lemma bheight_paint_Red: + "color t = Black \ bheight (paint Red t) = bheight t - 1" by (cases t) auto -lemma balL_inv2_with_inv1: - assumes "inv2 lt" "inv2 rt" "bheight lt + 1 = bheight rt" "inv1 rt" - shows "bheight (balL lt a rt) = bheight lt + 1" "inv2 (balL lt a rt)" +lemma balL_invh_with_invc: + assumes "invh lt" "invh rt" "bheight lt + 1 = bheight rt" "invc rt" + shows "bheight (balL lt a rt) = bheight lt + 1" "invh (balL lt a rt)" using assms -by (induct lt a rt rule: balL.induct) (auto simp: inv2_bal inv2_paint bheight_bal) +by (induct lt a rt rule: balL.induct) + (auto simp: invh_bal invh_paint bheight_bal bheight_paint_Red) -lemma balL_inv2_app: - assumes "inv2 lt" "inv2 rt" "bheight lt + 1 = bheight rt" "color rt = Black" - shows "inv2 (balL lt a rt)" +lemma balL_invh_app: + assumes "invh lt" "invh rt" "bheight lt + 1 = bheight rt" "color rt = Black" + shows "invh (balL lt a rt)" "bheight (balL lt a rt) = bheight rt" using assms -by (induct lt a rt rule: balL.induct) (auto simp add: inv2_bal bheight_bal) +by (induct lt a rt rule: balL.induct) (auto simp add: invh_bal bheight_bal) -lemma balL_inv1: "\inv1_root l; inv1 r; color r = Black\ \ inv1 (balL l a r)" -by (induct l a r rule: balL.induct) (simp_all add: inv1_bal) +lemma balL_invc: "\invc_sons l; invc r; color r = Black\ \ invc (balL l a r)" +by (induct l a r rule: balL.induct) (simp_all add: invc_bal) -lemma balL_inv1_root: "\ inv1_root lt; inv1 rt \ \ inv1_root (balL lt a rt)" -by (induct lt a rt rule: balL.induct) (auto simp: inv1_bal paint_inv1_root) +lemma balL_invc_sons: "\ invc_sons lt; invc rt \ \ invc_sons (balL lt a rt)" +by (induct lt a rt rule: balL.induct) (auto simp: invc_bal paint_invc_sons invc_sonsI) -lemma balR_inv2_with_inv1: - assumes "inv2 lt" "inv2 rt" "bheight lt = bheight rt + 1" "inv1 lt" - shows "inv2 (balR lt a rt) \ bheight (balR lt a rt) = bheight lt" +lemma balR_invh_with_invc: + assumes "invh lt" "invh rt" "bheight lt = bheight rt + 1" "invc lt" + shows "invh (balR lt a rt) \ bheight (balR lt a rt) = bheight lt" using assms -by(induct lt a rt rule: balR.induct)(auto simp: inv2_bal bheight_bal inv2_paint) +by(induct lt a rt rule: balR.induct) + (auto simp: invh_bal bheight_bal invh_paint bheight_paint_Red) -lemma balR_inv1: "\inv1 a; inv1_root b; color a = Black\ \ inv1 (balR a x b)" -by (induct a x b rule: balR.induct) (simp_all add: inv1_bal) +lemma invc_balR: "\invc a; invc_sons b; color a = Black\ \ invc (balR a x b)" +by (induct a x b rule: balR.induct) (simp_all add: invc_bal) -lemma balR_inv1_root: "\ inv1 lt; inv1_root rt \ \inv1_root (balR lt x rt)" -by (induct lt x rt rule: balR.induct) (auto simp: inv1_bal paint_inv1_root) +lemma invc_sons_balR: "\ invc lt; invc_sons rt \ \invc_sons (balR lt x rt)" +by (induct lt x rt rule: balR.induct) (auto simp: invc_bal paint_invc_sons invc_sonsI) -lemma combine_inv2: - assumes "inv2 lt" "inv2 rt" "bheight lt = bheight rt" - shows "bheight (combine lt rt) = bheight lt" "inv2 (combine lt rt)" +lemma invh_combine: + assumes "invh lt" "invh rt" "bheight lt = bheight rt" + shows "bheight (combine lt rt) = bheight lt" "invh (combine lt rt)" using assms by (induct lt rt rule: combine.induct) - (auto simp: balL_inv2_app split: tree.splits color.splits) + (auto simp: balL_invh_app split: tree.splits color.splits) -lemma combine_inv1: - assumes "inv1 lt" "inv1 rt" - shows "color lt = Black \ color rt = Black \ inv1 (combine lt rt)" - "inv1_root (combine lt rt)" +lemma invc_combine: + assumes "invc lt" "invc rt" + shows "color lt = Black \ color rt = Black \ invc (combine lt rt)" + "invc_sons (combine lt rt)" using assms by (induct lt rt rule: combine.induct) - (auto simp: balL_inv1 split: tree.splits color.splits) + (auto simp: balL_invc invc_sonsI split: tree.splits color.splits) -lemma - assumes "inv2 lt" "inv1 lt" +lemma assumes "invh lt" "invc lt" shows - "\inv2 rt; bheight lt = bheight rt; inv1 rt\ \ - inv2 (rbt_del_from_left x lt k v rt) \ - bheight (rbt_del_from_left x lt k v rt) = bheight lt \ - (color_of lt = B \ color_of rt = B \ inv1 (rbt_del_from_left x lt k v rt) \ - (color_of lt \ B \ color_of rt \ B) \ inv1l (rbt_del_from_left x lt k v rt))" - and "\inv2 rt; bheight lt = bheight rt; inv1 rt\ \ - inv2 (rbt_del_from_right x lt k v rt) \ - bheight (rbt_del_from_right x lt k v rt) = bheight lt \ - (color_of lt = B \ color_of rt = B \ inv1 (rbt_del_from_right x lt k v rt) \ - (color_of lt \ B \ color_of rt \ B) \ inv1l (rbt_del_from_right x lt k v rt))" - and rbt_del_inv1_inv2: "inv2 (rbt_del x lt) \ (color_of lt = R \ bheight (rbt_del x lt) = bheight lt \ inv1 (rbt_del x lt) - \ color_of lt = B \ bheight (rbt_del x lt) = bheight lt - 1 \ inv1l (rbt_del x lt))" + del_invc_invh: "invh (del x lt) \ (color lt = Red \ bheight (del x lt) = bheight lt \ invc (del x lt) + \ color lt = Black \ bheight (del x lt) = bheight lt - 1 \ invc_sons (del x lt))" +and "\invh rt; bheight lt = bheight rt; invc rt\ \ + invh (delL x lt k rt) \ + bheight (delL x lt k rt) = bheight lt \ + (color lt = Black \ color rt = Black \ invc (delL x lt k rt) \ + (color lt \ Black \ color rt \ Black) \ invc_sons (delL x lt k rt))" + and "\invh rt; bheight lt = bheight rt; invc rt\ \ + invh (delR x lt k rt) \ + bheight (delR x lt k rt) = bheight lt \ + (color lt = Black \ color rt = Black \ invc (delR x lt k rt) \ + (color lt \ Black \ color rt \ Black) \ invc_sons (delR x lt k rt))" using assms -proof (induct x lt k v rt and x lt k v rt and x lt rule: rbt_del_from_left_rbt_del_from_right_rbt_del.induct) +proof (induct x lt and x lt k rt and x lt k rt rule: del_delL_delR.induct) case (2 y c _ y') have "y = y' \ y < y' \ y > y'" by auto thus ?case proof (elim disjE) assume "y = y'" - with 2 show ?thesis by (cases c) (simp add: combine_inv2 combine_inv1)+ + with 2 show ?thesis + by (cases c) (simp_all add: invh_combine invc_combine) next assume "y < y'" - with 2 show ?thesis by (cases c) auto + with 2 show ?thesis by (cases c) (auto simp: invc_sonsI) next assume "y' < y" - with 2 show ?thesis by (cases c) auto + with 2 show ?thesis by (cases c) (auto simp: invc_sonsI) qed next - case (3 y lt z v rta y' ss bb) - thus ?case by (cases "color_of (Branch B lt z v rta) = B \ color_of bb = B") (simp add: balance_left_inv2_with_inv1 balance_left_inv1 balance_left_inv1l)+ + case (3 y lt z rta y' bb) + thus ?case by (cases "color (Node Black lt z rta) = Black \ color bb = Black") (simp add: balL_invh_with_invc balL_invc balL_invc_sons)+ next - case (5 y a y' ss lt z v rta) - thus ?case by (cases "color_of a = B \ color_of (Branch B lt z v rta) = B") (simp add: balance_right_inv2_with_inv1 balance_right_inv1 balance_right_inv1l)+ + case (5 y a y' lt z rta) + thus ?case by (cases "color a = Black \ color (Node Black lt z rta) = Black") (simp add: balR_invh_with_invc invc_balR invc_sons_balR)+ next - case ("6_1" y a y' ss) thus ?case by (cases "color_of a = B \ color_of Empty = B") simp+ + case ("6_1" y a y') thus ?case by (cases "color a = Black \ color Leaf = Black") simp+ qed auto -theorem rbt_delete_is_rbt [simp]: assumes "rbt t" shows "rbt (delete k t)" +theorem rbt_delete: "rbt t \ rbt (delete k t)" +by (metis delete_def rbt_def color_paint_Black del_invc_invh invc_paint_Black invc_sonsI invh_paint) + +text \Overall correctness:\ + +interpretation Set_by_Ordered +where empty = Leaf and isin = isin and insert = insert and delete = delete +and inorder = inorder and inv = rbt +proof (standard, goal_cases) + case 1 show ?case by simp +next + case 2 thus ?case by(simp add: isin_set) +next + case 3 thus ?case by(simp add: inorder_insert) +next + case 4 thus ?case by(simp add: inorder_delete) +next + case 5 thus ?case by (simp add: rbt_Leaf) +next + case 6 thus ?case by (simp add: rbt_insert) +next + case 7 thus ?case by (simp add: rbt_delete) +qed + + +subsection \Height-Size Relation\ + +text \By Daniel St\"uwe\ + +lemma color_RedE:"color t = Red \ invc t = + (\ l a r . t = R l a r \ color l = Black \ color r = Black \ invc l \ invc r)" +by (cases t) auto + +lemma rbt_induct[consumes 1]: + assumes "rbt t" + assumes [simp]: "P Leaf" + assumes "\ t l a r. \t = B l a r; invc t; invh t; Q(l); Q(r)\ \ P t" + assumes "\ t l a r. \t = R l a r; invc t; invh t; P(l); P(r)\ \ Q t" + assumes "\ t . P(t) \ Q(t)" + shows "P t" +using assms(1) unfolding rbt_def apply safe +proof (induction t rule: measure_induct[of size]) +case (1 t) + note * = 1 assms + show ?case proof (cases t) + case [simp]: (Node c l a r) + show ?thesis proof (cases c) + case Red thus ?thesis using 1 by simp + next + case [simp]: Black + show ?thesis + proof (cases "color l") + case Red + thus ?thesis using * by (cases "color r") (auto simp: color_RedE) + next + case Black + thus ?thesis using * by (cases "color r") (auto simp: color_RedE) + qed + qed + qed simp +qed + +lemma rbt_b_height: "rbt t \ bheight t * 2 \ height t" +by (induction t rule: rbt_induct[where Q="\ t. bheight t * 2 + 1 \ height t"]) auto + +lemma red_b_height: "invc t \ invh t \ bheight t * 2 + 1 \ height t" +apply (cases t) apply simp + using rbt_b_height unfolding rbt_def + by (cases "color t") fastforce+ + +lemma red_b_height2: "invc t \ invh t \ bheight t \ height t div 2" +using red_b_height by fastforce + +lemma rbt_b_height2: "bheight t \ height t" +by (induction t) auto + +lemma "rbt t \ size1 t \ 4 ^ (bheight t)" +by(induction t rule: rbt_induct[where Q="\ t. size1 t \ 2 * 4 ^ (bheight t)"]) auto + +lemma bheight_size_bound: "rbt t \ size1 t \ 2 ^ (bheight t)" +by (induction t rule: rbt_induct[where Q="\ t. size1 t \ 2 ^ (bheight t)"]) auto + +text \Balanced red-balck tree with all black nodes:\ +inductive balB :: "nat \ unit rbt \ bool" where +"balB 0 Leaf" | +"balB h t \ balB (Suc h) (B t () t)" + +inductive_cases [elim!]: "balB 0 t" +inductive_cases [elim]: "balB (Suc h) t" + +lemma balB_hs: "balB h t \ bheight t = height t" +by (induction h t rule: "balB.induct") auto + +lemma balB_h: "balB h t \ h = height t" +by (induction h t rule: "balB.induct") auto + +lemma "rbt t \ balB (bheight t) t' \ size t' \ size t" +by (induction t arbitrary: t' + rule: rbt_induct[where Q="\ t . \ h t'. balB (bheight t) t' \ size t' \ size t"]) + fastforce+ + +lemma balB_bh: "invc t \ invh t \ balB (bheight t) t' \ size t' \ size t" +by (induction t arbitrary: t') (fastforce split: if_split_asm)+ + +lemma balB_bh3:"\ balB h t; balB (h' + h) t' \ \ size t \ size t'" +by (induction h t arbitrary: t' h' rule: balB.induct) fastforce+ + +corollary balB_bh3': "\ balB h t; balB h' t'; h \ h' \ \ size t \ size t'" +using balB_bh3 le_Suc_ex by (fastforce simp: algebra_simps) + +lemma exist_pt: "\ t . balB h t" +by (induction h) (auto intro: balB.intros) + +corollary compact_pt: + assumes "invc t" "invh t" "h \ bheight t" "balB h t'" + shows "size t' \ size t" proof - - from assms have "inv2 t" and "inv1 t" unfolding rbt_def by auto - hence "inv2 (del k t) \ (color t = Red \ bheight (del k t) = bheight t \ inv1 (del k t) \ color t = Black \ bheight (del k t) = bheight t - 1 \ inv1_root (del k t))" - by (rule rbt_del_inv1_inv2) - hence "inv2 (del k t) \ inv1l (rbt_del k t)" by (cases "color_of t") auto - with assms show ?thesis - unfolding is_rbt_def rbt_delete_def - by (auto intro: paint_rbt_sorted rbt_del_rbt_sorted) + obtain t'' where "balB (bheight t) t''" using exist_pt by blast + thus ?thesis using assms balB_bh[of t t''] balB_bh3'[of h t' "bheight t" t''] by auto +qed + +lemma balB_bh2: "balB (bheight t) t'\ invc t \ invh t \ height t' \ height t" +apply (induction "(bheight t)" t' arbitrary: t rule: balB.induct) +using balB_h rbt_b_height2 by auto + +lemma balB_rbt: "balB h t \ rbt t" +unfolding rbt_def +by (induction h t rule: balB.induct) auto + +lemma balB_size[simp]: "balB h t \ size1 t = 2^h" +by (induction h t rule: balB.induct) auto + +text \Red-black tree (except that the root may be red) of minimal size +for a given height:\ + +inductive RB :: "nat \ unit rbt \ bool" where +"RB 0 Leaf" | +"balB (h div 2) t \ RB h t' \ color t' = Red \ RB (Suc h) (B t' () t)" | +"balB (h div 2) t \ RB h t' \ color t' = Black \ RB (Suc h) (R t' () t)" + +lemmas RB.intros[intro] + +lemma RB_invc: "RB h t \ invc t" +apply (induction h t rule: RB.induct) +using balB_rbt unfolding rbt_def by auto + +lemma RB_h: "RB h t \ h = height t" +apply (induction h t rule: RB.induct) +using balB_h by auto + +lemma RB_mod: "RB h t \ (color t = Black \ h mod 2 = 0)" +apply (induction h t rule: RB.induct) +apply auto +by presburger + +lemma RB_b_height: "RB h t \ height t div 2 = bheight t" +proof (induction h t rule: RB.induct) + case 1 + thus ?case by auto +next + case (2 h t t') + with RB_mod obtain n where "2*n + 1 = h" + by (metis color.distinct(1) mod_div_equality2 parity) + with 2 balB_h RB_h show ?case by auto +next + case (3 h t t') + with RB_mod[OF 3(2)] parity obtain n where "2*n = h" by blast + with 3 balB_h RB_h show ?case by auto qed -*) + +lemma weak_RB_induct[consumes 1]: + "RB h t \ P 0 \\ \ (\h t t' c . balB (h div 2) t \ RB h t' \ + P h t' \ P (Suc h) (Node c t' () t)) \ P h t" +using RB.induct by metis + +lemma RB_invh: "RB h t \ invh t" +apply (induction h t rule: weak_RB_induct) + using balB_h balB_hs RB_h balB_rbt RB_b_height + unfolding rbt_def +by auto + +lemma RB_bheight_minimal: + "\RB (height t') t; invc t'; invh t'\ \ bheight t \ bheight t'" +using RB_b_height RB_h red_b_height2 by fastforce + +lemma RB_minimal: "RB (height t') t \ invh t \ invc t' \ invh t' \ size t \ size t'" +proof (induction "(height t')" t arbitrary: t' rule: weak_RB_induct) + case 1 thus ?case by auto +next + case (2 h t t'') + have ***: "size (Node c t'' () t) \ size t'" + if assms: + "\ (t' :: 'a rbt) . \ h = height t'; invh t''; invc t'; invh t' \ + \ size t'' \ size t'" + "Suc h = height t'" "balB (h div 2) t" "RB h t''" + "invc t'" "invh t'" "height l \ height r" + and tt[simp]:"t' = Node c l a r" and last: "invh (Node c t'' () t)" + for t' :: "'a rbt" and c l a r + proof - + from assms have inv: "invc r" "invh r" by auto + from assms have "height l = h" using max_def by auto + with RB_bheight_minimal[of l t''] have + "bheight t \ bheight r" using assms last by auto + with compact_pt[OF inv] balB_h balB_hs have + "size t \ size r" using assms(3) by auto moreover + have "size t'' \ size l" using assms last by auto ultimately + show ?thesis by simp + qed + + from 2 obtain c l a r where + t': "t' = Node c l a r" by (cases t') auto + with 2 have inv: "invc l" "invh l" "invc r" "invh r" by auto + show ?case proof (cases "height r \ height l") + case True thus ?thesis using ***[OF 2(3,4,1,2,6,7)] t' 2(5) by auto + next + case False + obtain t''' where t''' : "t''' = Node c r a l" "invc t'''" "invh t'''" using 2 t' by auto + have "size t''' = size t'" and 4 : "Suc h = height t'''" using 2(4) t' t''' by auto + thus ?thesis using ***[OF 2(3) 4 2(1,2) t'''(2,3) _ t'''(1)] 2(5) False by auto + qed +qed + +lemma RB_size: "RB h t \ size1 t + 1 = 2^((h+1) div 2) + 2^(h div 2)" +by (induction h t rule: "RB.induct" ) auto + +lemma RB_exist: "\ t . RB h t" +proof (induction h) + case (Suc n) + obtain r where r: "balB (n div 2) r" using exist_pt by blast + obtain l where l: "RB n l" using Suc by blast + obtain t where + "color l = Red \ t = B l () r" + "color l = Black \ t = R l () r" by auto + with l and r have "RB (Suc n) t" by (cases "color l") auto + thus ?case by auto +qed auto + +lemma bound: + assumes "invc t" "invh t" and [simp]:"height t = h" + shows "size t \ 2^((h+1) div 2) + 2^(h div 2) - 2" +proof - + obtain t' where t': "RB h t'" using RB_exist by auto + show ?thesis using RB_size[OF t'] + RB_minimal[OF _ _ assms(1,2), simplified, OF t' RB_invh[OF t']] assms t' + unfolding size1_def by auto +qed + +corollary "rbt t \ h = height t \ size t \ 2^((h+1) div 2) + 2^(h div 2) - 2" +using bound unfolding rbt_def by blast + end diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Splay_Map.thy --- a/src/HOL/Data_Structures/Splay_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Splay_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -42,7 +42,7 @@ termination splay by lexicographic_order -lemma splay_code: "splay (x::_::cmp) t = (case t of Leaf \ Leaf | +lemma splay_code: "splay (x::_::linorder) t = (case t of Leaf \ Leaf | Node al a ar \ (case cmp x (fst a) of EQ \ t | LT \ (case al of diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Splay_Set.thy --- a/src/HOL/Data_Structures/Splay_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Splay_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -51,7 +51,7 @@ "\ x = x'; y = y'; z = z' \ \ case_tree x y z = case_tree x' y' z'" by auto -lemma splay_code: "splay (x::_::cmp) t = (case t of Leaf \ Leaf | +lemma splay_code: "splay (x::_::linorder) t = (case t of Leaf \ Leaf | Node al a ar \ (case cmp x a of EQ \ t | LT \ (case al of @@ -83,7 +83,7 @@ hide_const (open) insert -fun insert :: "'a::cmp \ 'a tree \ 'a tree" where +fun insert :: "'a::linorder \ 'a tree \ 'a tree" where "insert x t = (if t = Leaf then Node Leaf x Leaf else case splay x t of diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree234_Map.thy --- a/src/HOL/Data_Structures/Tree234_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree234_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -10,7 +10,7 @@ subsection \Map operations on 2-3-4 trees\ -fun lookup :: "('a::cmp * 'b) tree234 \ 'a \ 'b option" where +fun lookup :: "('a::linorder * 'b) tree234 \ 'a \ 'b option" where "lookup Leaf x = None" | "lookup (Node2 l (a,b) r) x = (case cmp x a of LT \ lookup l x | @@ -30,7 +30,7 @@ GT \ (case cmp x a3 of LT \ lookup t3 x | EQ \ Some b3 | GT \ lookup t4 x))" -fun upd :: "'a::cmp \ 'b \ ('a*'b) tree234 \ ('a*'b) up\<^sub>i" where +fun upd :: "'a::linorder \ 'b \ ('a*'b) tree234 \ ('a*'b) up\<^sub>i" where "upd x y Leaf = Up\<^sub>i Leaf (x,y) Leaf" | "upd x y (Node2 l ab r) = (case cmp x (fst ab) of LT \ (case upd x y l of @@ -72,10 +72,10 @@ T\<^sub>i t4' => T\<^sub>i (Node4 t1 ab1 t2 ab2 t3 ab3 t4') | Up\<^sub>i t41 q t42 => Up\<^sub>i (Node2 t1 ab1 t2) ab2 (Node3 t3 ab3 t41 q t42))))" -definition update :: "'a::cmp \ 'b \ ('a*'b) tree234 \ ('a*'b) tree234" where +definition update :: "'a::linorder \ 'b \ ('a*'b) tree234 \ ('a*'b) tree234" where "update x y t = tree\<^sub>i(upd x y t)" -fun del :: "'a::cmp \ ('a*'b) tree234 \ ('a*'b) up\<^sub>d" where +fun del :: "'a::linorder \ ('a*'b) tree234 \ ('a*'b) up\<^sub>d" where "del x Leaf = T\<^sub>d Leaf" | "del x (Node2 Leaf ab1 Leaf) = (if x=fst ab1 then Up\<^sub>d Leaf else T\<^sub>d(Node2 Leaf ab1 Leaf))" | "del x (Node3 Leaf ab1 Leaf ab2 Leaf) = T\<^sub>d(if x=fst ab1 then Node2 Leaf ab2 Leaf @@ -107,7 +107,7 @@ EQ \ let (ab',t4') = del_min t4 in node44 t1 ab1 t2 ab2 t3 ab' t4' | GT \ node44 t1 ab1 t2 ab2 t3 ab3 (del x t4)))" -definition delete :: "'a::cmp \ ('a*'b) tree234 \ ('a*'b) tree234" where +definition delete :: "'a::linorder \ ('a*'b) tree234 \ ('a*'b) tree234" where "delete x t = tree\<^sub>d(del x t)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree234_Set.thy --- a/src/HOL/Data_Structures/Tree234_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree234_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -11,7 +11,7 @@ subsection \Set operations on 2-3-4 trees\ -fun isin :: "'a::cmp tree234 \ 'a \ bool" where +fun isin :: "'a::linorder tree234 \ 'a \ bool" where "isin Leaf x = False" | "isin (Node2 l a r) x = (case cmp x a of LT \ isin l x | EQ \ True | GT \ isin r x)" | @@ -38,7 +38,7 @@ "tree\<^sub>i (T\<^sub>i t) = t" | "tree\<^sub>i (Up\<^sub>i l a r) = Node2 l a r" -fun ins :: "'a::cmp \ 'a tree234 \ 'a up\<^sub>i" where +fun ins :: "'a::linorder \ 'a tree234 \ 'a up\<^sub>i" where "ins x Leaf = Up\<^sub>i Leaf x Leaf" | "ins x (Node2 l a r) = (case cmp x a of @@ -91,7 +91,7 @@ hide_const insert -definition insert :: "'a::cmp \ 'a tree234 \ 'a tree234" where +definition insert :: "'a::linorder \ 'a tree234 \ 'a tree234" where "insert x t = tree\<^sub>i(ins x t)" datatype 'a up\<^sub>d = T\<^sub>d "'a tree234" | Up\<^sub>d "'a tree234" @@ -162,7 +162,7 @@ "del_min (Node3 l a m b r) = (let (x,l') = del_min l in (x, node31 l' a m b r))" | "del_min (Node4 l a m b n c r) = (let (x,l') = del_min l in (x, node41 l' a m b n c r))" -fun del :: "'a::cmp \ 'a tree234 \ 'a up\<^sub>d" where +fun del :: "'a::linorder \ 'a tree234 \ 'a up\<^sub>d" where "del k Leaf = T\<^sub>d Leaf" | "del k (Node2 Leaf p Leaf) = (if k=p then Up\<^sub>d Leaf else T\<^sub>d(Node2 Leaf p Leaf))" | "del k (Node3 Leaf p Leaf q Leaf) = T\<^sub>d(if k=p then Node2 Leaf q Leaf @@ -194,7 +194,7 @@ EQ \ let (c',r') = del_min r in node44 l a m b n c' r' | GT \ node44 l a m b n c (del k r)))" -definition delete :: "'a::cmp \ 'a tree234 \ 'a tree234" where +definition delete :: "'a::linorder \ 'a tree234 \ 'a tree234" where "delete x t = tree\<^sub>d(del x t)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree23_Map.thy --- a/src/HOL/Data_Structures/Tree23_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree23_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -8,7 +8,7 @@ Map_by_Ordered begin -fun lookup :: "('a::cmp * 'b) tree23 \ 'a \ 'b option" where +fun lookup :: "('a::linorder * 'b) tree23 \ 'a \ 'b option" where "lookup Leaf x = None" | "lookup (Node2 l (a,b) r) x = (case cmp x a of LT \ lookup l x | @@ -22,7 +22,7 @@ EQ \ Some b2 | GT \ lookup r x))" -fun upd :: "'a::cmp \ 'b \ ('a*'b) tree23 \ ('a*'b) up\<^sub>i" where +fun upd :: "'a::linorder \ 'b \ ('a*'b) tree23 \ ('a*'b) up\<^sub>i" where "upd x y Leaf = Up\<^sub>i Leaf (x,y) Leaf" | "upd x y (Node2 l ab r) = (case cmp x (fst ab) of LT \ (case upd x y l of @@ -46,10 +46,10 @@ T\<^sub>i r' => T\<^sub>i (Node3 l ab1 m ab2 r') | Up\<^sub>i r1 ab' r2 => Up\<^sub>i (Node2 l ab1 m) ab2 (Node2 r1 ab' r2))))" -definition update :: "'a::cmp \ 'b \ ('a*'b) tree23 \ ('a*'b) tree23" where +definition update :: "'a::linorder \ 'b \ ('a*'b) tree23 \ ('a*'b) tree23" where "update a b t = tree\<^sub>i(upd a b t)" -fun del :: "'a::cmp \ ('a*'b) tree23 \ ('a*'b) up\<^sub>d" where +fun del :: "'a::linorder \ ('a*'b) tree23 \ ('a*'b) up\<^sub>d" where "del x Leaf = T\<^sub>d Leaf" | "del x (Node2 Leaf ab1 Leaf) = (if x=fst ab1 then Up\<^sub>d Leaf else T\<^sub>d(Node2 Leaf ab1 Leaf))" | "del x (Node3 Leaf ab1 Leaf ab2 Leaf) = T\<^sub>d(if x=fst ab1 then Node2 Leaf ab2 Leaf @@ -66,7 +66,7 @@ EQ \ let (ab2',r') = del_min r in node33 l ab1 m ab2' r' | GT \ node33 l ab1 m ab2 (del x r)))" -definition delete :: "'a::cmp \ ('a*'b) tree23 \ ('a*'b) tree23" where +definition delete :: "'a::linorder \ ('a*'b) tree23 \ ('a*'b) tree23" where "delete x t = tree\<^sub>d(del x t)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree23_Set.thy --- a/src/HOL/Data_Structures/Tree23_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree23_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -9,7 +9,7 @@ Set_by_Ordered begin -fun isin :: "'a::cmp tree23 \ 'a \ bool" where +fun isin :: "'a::linorder tree23 \ 'a \ bool" where "isin Leaf x = False" | "isin (Node2 l a r) x = (case cmp x a of @@ -32,7 +32,7 @@ "tree\<^sub>i (T\<^sub>i t) = t" | "tree\<^sub>i (Up\<^sub>i l a r) = Node2 l a r" -fun ins :: "'a::cmp \ 'a tree23 \ 'a up\<^sub>i" where +fun ins :: "'a::linorder \ 'a tree23 \ 'a up\<^sub>i" where "ins x Leaf = Up\<^sub>i Leaf x Leaf" | "ins x (Node2 l a r) = (case cmp x a of @@ -66,7 +66,7 @@ hide_const insert -definition insert :: "'a::cmp \ 'a tree23 \ 'a tree23" where +definition insert :: "'a::linorder \ 'a tree23 \ 'a tree23" where "insert x t = tree\<^sub>i(ins x t)" datatype 'a up\<^sub>d = T\<^sub>d "'a tree23" | Up\<^sub>d "'a tree23" @@ -108,7 +108,7 @@ "del_min (Node2 l a r) = (let (x,l') = del_min l in (x, node21 l' a r))" | "del_min (Node3 l a m b r) = (let (x,l') = del_min l in (x, node31 l' a m b r))" -fun del :: "'a::cmp \ 'a tree23 \ 'a up\<^sub>d" where +fun del :: "'a::linorder \ 'a tree23 \ 'a up\<^sub>d" where "del x Leaf = T\<^sub>d Leaf" | "del x (Node2 Leaf a Leaf) = (if x = a then Up\<^sub>d Leaf else T\<^sub>d(Node2 Leaf a Leaf))" | @@ -131,7 +131,7 @@ EQ \ let (b',r') = del_min r in node33 l a m b' r' | GT \ node33 l a m b (del x r)))" -definition delete :: "'a::cmp \ 'a tree23 \ 'a tree23" where +definition delete :: "'a::linorder \ 'a tree23 \ 'a tree23" where "delete x t = tree\<^sub>d(del x t)" diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree_Map.thy --- a/src/HOL/Data_Structures/Tree_Map.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree_Map.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,6 +1,6 @@ (* Author: Tobias Nipkow *) -section {* Unbalanced Tree as Map *} +section \Unbalanced Tree Implementation of Map\ theory Tree_Map imports @@ -8,19 +8,19 @@ Map_by_Ordered begin -fun lookup :: "('a::cmp*'b) tree \ 'a \ 'b option" where +fun lookup :: "('a::linorder*'b) tree \ 'a \ 'b option" where "lookup Leaf x = None" | "lookup (Node l (a,b) r) x = (case cmp x a of LT \ lookup l x | GT \ lookup r x | EQ \ Some b)" -fun update :: "'a::cmp \ 'b \ ('a*'b) tree \ ('a*'b) tree" where +fun update :: "'a::linorder \ 'b \ ('a*'b) tree \ ('a*'b) tree" where "update x y Leaf = Node Leaf (x,y) Leaf" | "update x y (Node l (a,b) r) = (case cmp x a of LT \ Node (update x y l) (a,b) r | EQ \ Node l (x,y) r | GT \ Node l (a,b) (update x y r))" -fun delete :: "'a::cmp \ ('a*'b) tree \ ('a*'b) tree" where +fun delete :: "'a::linorder \ ('a*'b) tree \ ('a*'b) tree" where "delete x Leaf = Leaf" | "delete x (Node l (a,b) r) = (case cmp x a of LT \ Node (delete x l) (a,b) r | diff -r 9789ccc2a477 -r def97df48390 src/HOL/Data_Structures/Tree_Set.thy --- a/src/HOL/Data_Structures/Tree_Set.thy Thu Jul 07 17:34:39 2016 +0200 +++ b/src/HOL/Data_Structures/Tree_Set.thy Thu Jul 07 18:08:10 2016 +0200 @@ -1,6 +1,6 @@ (* Author: Tobias Nipkow *) -section {* Tree Implementation of Sets *} +section \Unbalanced Tree Implementation of Set\ theory Tree_Set imports @@ -9,7 +9,7 @@ Set_by_Ordered begin -fun isin :: "'a::cmp tree \ 'a \ bool" where +fun isin :: "'a::linorder tree \ 'a \ bool" where "isin Leaf x = False" | "isin (Node l a r) x = (case cmp x a of @@ -19,7 +19,7 @@ hide_const (open) insert -fun insert :: "'a::cmp \ 'a tree \ 'a tree" where +fun insert :: "'a::linorder \ 'a tree \ 'a tree" where "insert x Leaf = Node Leaf x Leaf" | "insert x (Node l a r) = (case cmp x a of @@ -31,7 +31,7 @@ "del_min (Node l a r) = (if l = Leaf then (a,r) else let (x,l') = del_min l in (x, Node l' a r))" -fun delete :: "'a::cmp \ 'a tree \ 'a tree" where +fun delete :: "'a::linorder \ 'a tree \ 'a tree" where "delete x Leaf = Leaf" | "delete x (Node l a r) = (case cmp x a of