src/HOL/Library/Tree.thy
author haftmann
Mon Jun 05 15:59:41 2017 +0200 (2017-06-05)
changeset 66010 2f7d39285a1a
parent 65340 8ec91f7eca37
child 66606 f23f044148d3
permissions -rw-r--r--
executable domain membership checks
     1 (* Author: Tobias Nipkow *)
     2 (* Todo: minimal ipl of balanced trees *)
     3 
     4 section \<open>Binary Tree\<close>
     5 
     6 theory Tree
     7 imports Main
     8 begin
     9 
    10 datatype 'a tree =
    11   Leaf ("\<langle>\<rangle>") |
    12   Node "'a tree" (root_val: 'a) "'a tree" ("(1\<langle>_,/ _,/ _\<rangle>)")
    13 datatype_compat tree
    14 
    15 text\<open>Can be seen as counting the number of leaves rather than nodes:\<close>
    16 
    17 definition size1 :: "'a tree \<Rightarrow> nat" where
    18 "size1 t = size t + 1"
    19 
    20 fun subtrees :: "'a tree \<Rightarrow> 'a tree set" where
    21 "subtrees \<langle>\<rangle> = {\<langle>\<rangle>}" |
    22 "subtrees (\<langle>l, a, r\<rangle>) = insert \<langle>l, a, r\<rangle> (subtrees l \<union> subtrees r)"
    23 
    24 fun mirror :: "'a tree \<Rightarrow> 'a tree" where
    25 "mirror \<langle>\<rangle> = Leaf" |
    26 "mirror \<langle>l,x,r\<rangle> = \<langle>mirror r, x, mirror l\<rangle>"
    27 
    28 class height = fixes height :: "'a \<Rightarrow> nat"
    29 
    30 instantiation tree :: (type)height
    31 begin
    32 
    33 fun height_tree :: "'a tree => nat" where
    34 "height Leaf = 0" |
    35 "height (Node t1 a t2) = max (height t1) (height t2) + 1"
    36 
    37 instance ..
    38 
    39 end
    40 
    41 fun min_height :: "'a tree \<Rightarrow> nat" where
    42 "min_height Leaf = 0" |
    43 "min_height (Node l _ r) = min (min_height l) (min_height r) + 1"
    44 
    45 fun complete :: "'a tree \<Rightarrow> bool" where
    46 "complete Leaf = True" |
    47 "complete (Node l x r) = (complete l \<and> complete r \<and> height l = height r)"
    48 
    49 definition balanced :: "'a tree \<Rightarrow> bool" where
    50 "balanced t = (height t - min_height t \<le> 1)"
    51 
    52 text \<open>Weight balanced:\<close>
    53 fun wbalanced :: "'a tree \<Rightarrow> bool" where
    54 "wbalanced Leaf = True" |
    55 "wbalanced (Node l x r) = (abs(int(size l) - int(size r)) \<le> 1 \<and> wbalanced l \<and> wbalanced r)"
    56 
    57 text \<open>Internal path length:\<close>
    58 fun ipl :: "'a tree \<Rightarrow> nat" where
    59 "ipl Leaf = 0 " |
    60 "ipl (Node l _ r) = ipl l + size l + ipl r + size r"
    61 
    62 fun preorder :: "'a tree \<Rightarrow> 'a list" where
    63 "preorder \<langle>\<rangle> = []" |
    64 "preorder \<langle>l, x, r\<rangle> = x # preorder l @ preorder r"
    65 
    66 fun inorder :: "'a tree \<Rightarrow> 'a list" where
    67 "inorder \<langle>\<rangle> = []" |
    68 "inorder \<langle>l, x, r\<rangle> = inorder l @ [x] @ inorder r"
    69 
    70 text\<open>A linear version avoiding append:\<close>
    71 fun inorder2 :: "'a tree \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    72 "inorder2 \<langle>\<rangle> xs = xs" |
    73 "inorder2 \<langle>l, x, r\<rangle> xs = inorder2 l (x # inorder2 r xs)"
    74 
    75 fun postorder :: "'a tree \<Rightarrow> 'a list" where
    76 "postorder \<langle>\<rangle> = []" |
    77 "postorder \<langle>l, x, r\<rangle> = postorder l @ postorder r @ [x]"
    78 
    79 text\<open>Binary Search Tree:\<close>
    80 fun (in linorder) bst :: "'a tree \<Rightarrow> bool" where
    81 "bst \<langle>\<rangle> \<longleftrightarrow> True" |
    82 "bst \<langle>l, a, r\<rangle> \<longleftrightarrow> bst l \<and> bst r \<and> (\<forall>x\<in>set_tree l. x < a) \<and> (\<forall>x\<in>set_tree r. a < x)"
    83 
    84 text\<open>Binary Search Tree with duplicates:\<close>
    85 fun (in linorder) bst_eq :: "'a tree \<Rightarrow> bool" where
    86 "bst_eq \<langle>\<rangle> \<longleftrightarrow> True" |
    87 "bst_eq \<langle>l,a,r\<rangle> \<longleftrightarrow>
    88  bst_eq l \<and> bst_eq r \<and> (\<forall>x\<in>set_tree l. x \<le> a) \<and> (\<forall>x\<in>set_tree r. a \<le> x)"
    89 
    90 fun (in linorder) heap :: "'a tree \<Rightarrow> bool" where
    91 "heap Leaf = True" |
    92 "heap (Node l m r) =
    93   (heap l \<and> heap r \<and> (\<forall>x \<in> set_tree l \<union> set_tree r. m \<le> x))"
    94 
    95 
    96 subsection \<open>@{const map_tree}\<close>
    97 
    98 lemma eq_map_tree_Leaf[simp]: "map_tree f t = Leaf \<longleftrightarrow> t = Leaf"
    99 by (rule tree.map_disc_iff)
   100 
   101 lemma eq_Leaf_map_tree[simp]: "Leaf = map_tree f t \<longleftrightarrow> t = Leaf"
   102 by (cases t) auto
   103 
   104 
   105 subsection \<open>@{const size}\<close>
   106 
   107 lemma size1_simps[simp]:
   108   "size1 \<langle>\<rangle> = 1"
   109   "size1 \<langle>l, x, r\<rangle> = size1 l + size1 r"
   110 by (simp_all add: size1_def)
   111 
   112 lemma size1_ge0[simp]: "0 < size1 t"
   113 by (simp add: size1_def)
   114 
   115 lemma eq_size_0[simp]: "size t = 0 \<longleftrightarrow> t = Leaf"
   116 by(cases t) auto
   117 
   118 lemma eq_0_size[simp]: "0 = size t \<longleftrightarrow> t = Leaf"
   119 by(cases t) auto
   120 
   121 lemma neq_Leaf_iff: "(t \<noteq> \<langle>\<rangle>) = (\<exists>l a r. t = \<langle>l, a, r\<rangle>)"
   122 by (cases t) auto
   123 
   124 lemma size_map_tree[simp]: "size (map_tree f t) = size t"
   125 by (induction t) auto
   126 
   127 lemma size1_map_tree[simp]: "size1 (map_tree f t) = size1 t"
   128 by (simp add: size1_def)
   129 
   130 
   131 subsection \<open>@{const set_tree}\<close>
   132 
   133 lemma eq_set_tree_empty[simp]: "set_tree t = {} \<longleftrightarrow> t = Leaf"
   134 by (cases t) auto
   135 
   136 lemma eq_empty_set_tree[simp]: "{} = set_tree t \<longleftrightarrow> t = Leaf"
   137 by (cases t) auto
   138 
   139 lemma finite_set_tree[simp]: "finite(set_tree t)"
   140 by(induction t) auto
   141 
   142 
   143 subsection \<open>@{const subtrees}\<close>
   144 
   145 lemma neq_subtrees_empty[simp]: "subtrees t \<noteq> {}"
   146 by (cases t)(auto)
   147 
   148 lemma neq_empty_subtrees[simp]: "{} \<noteq> subtrees t"
   149 by (cases t)(auto)
   150 
   151 lemma set_treeE: "a \<in> set_tree t \<Longrightarrow> \<exists>l r. \<langle>l, a, r\<rangle> \<in> subtrees t"
   152 by (induction t)(auto)
   153 
   154 lemma Node_notin_subtrees_if[simp]: "a \<notin> set_tree t \<Longrightarrow> Node l a r \<notin> subtrees t"
   155 by (induction t) auto
   156 
   157 lemma in_set_tree_if: "\<langle>l, a, r\<rangle> \<in> subtrees t \<Longrightarrow> a \<in> set_tree t"
   158 by (metis Node_notin_subtrees_if)
   159 
   160 
   161 subsection \<open>@{const height} and @{const min_height}\<close>
   162 
   163 lemma eq_height_0[simp]: "height t = 0 \<longleftrightarrow> t = Leaf"
   164 by(cases t) auto
   165 
   166 lemma eq_0_height[simp]: "0 = height t \<longleftrightarrow> t = Leaf"
   167 by(cases t) auto
   168 
   169 lemma height_map_tree[simp]: "height (map_tree f t) = height t"
   170 by (induction t) auto
   171 
   172 lemma height_le_size_tree: "height t \<le> size (t::'a tree)"
   173 by (induction t) auto
   174 
   175 lemma size1_height: "size1 t \<le> 2 ^ height (t::'a tree)"
   176 proof(induction t)
   177   case (Node l a r)
   178   show ?case
   179   proof (cases "height l \<le> height r")
   180     case True
   181     have "size1(Node l a r) = size1 l + size1 r" by simp
   182     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r" using Node.IH by arith
   183     also have "\<dots> \<le> 2 ^ height r + 2 ^ height r" using True by simp
   184     also have "\<dots> = 2 ^ height (Node l a r)"
   185       using True by (auto simp: max_def mult_2)
   186     finally show ?thesis .
   187   next
   188     case False
   189     have "size1(Node l a r) = size1 l + size1 r" by simp
   190     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r" using Node.IH by arith
   191     also have "\<dots> \<le> 2 ^ height l + 2 ^ height l" using False by simp
   192     finally show ?thesis using False by (auto simp: max_def mult_2)
   193   qed
   194 qed simp
   195 
   196 corollary size_height: "size t \<le> 2 ^ height (t::'a tree) - 1"
   197 using size1_height[of t, unfolded size1_def] by(arith)
   198 
   199 lemma height_subtrees: "s \<in> subtrees t \<Longrightarrow> height s \<le> height t"
   200 by (induction t) auto
   201 
   202 
   203 lemma min_height_le_height: "min_height t \<le> height t"
   204 by(induction t) auto
   205 
   206 lemma min_height_map_tree[simp]: "min_height (map_tree f t) = min_height t"
   207 by (induction t) auto
   208 
   209 lemma min_height_size1: "2 ^ min_height t \<le> size1 t"
   210 proof(induction t)
   211   case (Node l a r)
   212   have "(2::nat) ^ min_height (Node l a r) \<le> 2 ^ min_height l + 2 ^ min_height r"
   213     by (simp add: min_def)
   214   also have "\<dots> \<le> size1(Node l a r)" using Node.IH by simp
   215   finally show ?case .
   216 qed simp
   217 
   218 
   219 subsection \<open>@{const complete}\<close>
   220 
   221 lemma complete_iff_height: "complete t \<longleftrightarrow> (min_height t = height t)"
   222 apply(induction t)
   223  apply simp
   224 apply (simp add: min_def max_def)
   225 by (metis le_antisym le_trans min_height_le_height)
   226 
   227 lemma size1_if_complete: "complete t \<Longrightarrow> size1 t = 2 ^ height t"
   228 by (induction t) auto
   229 
   230 lemma size_if_complete: "complete t \<Longrightarrow> size t = 2 ^ height t - 1"
   231 using size1_if_complete[simplified size1_def] by fastforce
   232 
   233 lemma complete_if_size1_height: "size1 t = 2 ^ height t \<Longrightarrow> complete t"
   234 proof (induct "height t" arbitrary: t)
   235   case 0 thus ?case by (simp)
   236 next
   237   case (Suc h)
   238   hence "t \<noteq> Leaf" by auto
   239   then obtain l a r where [simp]: "t = Node l a r"
   240     by (auto simp: neq_Leaf_iff)
   241   have 1: "height l \<le> h" and 2: "height r \<le> h" using Suc(2) by(auto)
   242   have 3: "\<not> height l < h"
   243   proof
   244     assume 0: "height l < h"
   245     have "size1 t = size1 l + size1 r" by simp
   246     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r"
   247       using size1_height[of l] size1_height[of r] by arith
   248     also have " \<dots> < 2 ^ h + 2 ^ height r" using 0 by (simp)
   249     also have " \<dots> \<le> 2 ^ h + 2 ^ h" using 2 by (simp)
   250     also have "\<dots> = 2 ^ (Suc h)" by (simp)
   251     also have "\<dots> = size1 t" using Suc(2,3) by simp
   252     finally have "size1 t < size1 t" .
   253     thus False by (simp)
   254   qed
   255   have 4: "\<not> height r < h"
   256   proof
   257     assume 0: "height r < h"
   258     have "size1 t = size1 l + size1 r" by simp
   259     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r"
   260       using size1_height[of l] size1_height[of r] by arith
   261     also have " \<dots> < 2 ^ height l + 2 ^ h" using 0 by (simp)
   262     also have " \<dots> \<le> 2 ^ h + 2 ^ h" using 1 by (simp)
   263     also have "\<dots> = 2 ^ (Suc h)" by (simp)
   264     also have "\<dots> = size1 t" using Suc(2,3) by simp
   265     finally have "size1 t < size1 t" .
   266     thus False by (simp)
   267   qed
   268   from 1 2 3 4 have *: "height l = h" "height r = h" by linarith+
   269   hence "size1 l = 2 ^ height l" "size1 r = 2 ^ height r"
   270     using Suc(3) size1_height[of l] size1_height[of r] by (auto)
   271   with * Suc(1) show ?case by simp
   272 qed
   273 
   274 text\<open>The following proof involves \<open>\<ge>\<close>/\<open>>\<close> chains rather than the standard
   275 \<open>\<le>\<close>/\<open><\<close> chains. To chain the elements together the transitivity rules \<open>xtrans\<close>
   276 are used.\<close>
   277 
   278 lemma complete_if_size1_min_height: "size1 t = 2 ^ min_height t \<Longrightarrow> complete t"
   279 proof (induct "min_height t" arbitrary: t)
   280   case 0 thus ?case by (simp add: size1_def)
   281 next
   282   case (Suc h)
   283   hence "t \<noteq> Leaf" by auto
   284   then obtain l a r where [simp]: "t = Node l a r"
   285     by (auto simp: neq_Leaf_iff)
   286   have 1: "h \<le> min_height l" and 2: "h \<le> min_height r" using Suc(2) by(auto)
   287   have 3: "\<not> h < min_height l"
   288   proof
   289     assume 0: "h < min_height l"
   290     have "size1 t = size1 l + size1 r" by simp
   291     also note min_height_size1[of l]
   292     also(xtrans) note min_height_size1[of r]
   293     also(xtrans) have "(2::nat) ^ min_height l > 2 ^ h"
   294         using 0 by (simp add: diff_less_mono)
   295     also(xtrans) have "(2::nat) ^ min_height r \<ge> 2 ^ h" using 2 by simp
   296     also(xtrans) have "(2::nat) ^ h + 2 ^ h = 2 ^ (Suc h)" by (simp)
   297     also have "\<dots> = size1 t" using Suc(2,3) by simp
   298     finally show False by (simp add: diff_le_mono)
   299   qed
   300   have 4: "\<not> h < min_height r"
   301   proof
   302     assume 0: "h < min_height r"
   303     have "size1 t = size1 l + size1 r" by simp
   304     also note min_height_size1[of l]
   305     also(xtrans) note min_height_size1[of r]
   306     also(xtrans) have "(2::nat) ^ min_height r > 2 ^ h"
   307         using 0 by (simp add: diff_less_mono)
   308     also(xtrans) have "(2::nat) ^ min_height l \<ge> 2 ^ h" using 1 by simp
   309     also(xtrans) have "(2::nat) ^ h + 2 ^ h = 2 ^ (Suc h)" by (simp)
   310     also have "\<dots> = size1 t" using Suc(2,3) by simp
   311     finally show False by (simp add: diff_le_mono)
   312   qed
   313   from 1 2 3 4 have *: "min_height l = h" "min_height r = h" by linarith+
   314   hence "size1 l = 2 ^ min_height l" "size1 r = 2 ^ min_height r"
   315     using Suc(3) min_height_size1[of l] min_height_size1[of r] by (auto)
   316   with * Suc(1) show ?case
   317     by (simp add: complete_iff_height)
   318 qed
   319 
   320 lemma complete_iff_size1: "complete t \<longleftrightarrow> size1 t = 2 ^ height t"
   321 using complete_if_size1_height size1_if_complete by blast
   322 
   323 text\<open>Better bounds for incomplete trees:\<close>
   324 
   325 lemma size1_height_if_incomplete:
   326   "\<not> complete t \<Longrightarrow> size1 t < 2 ^ height t"
   327 by (meson antisym_conv complete_iff_size1 not_le size1_height)
   328 
   329 lemma min_height_size1_if_incomplete:
   330   "\<not> complete t \<Longrightarrow> 2 ^ min_height t < size1 t"
   331 by (metis complete_if_size1_min_height le_less min_height_size1)
   332 
   333 
   334 subsection \<open>@{const balanced}\<close>
   335 
   336 lemma balanced_subtreeL: "balanced (Node l x r) \<Longrightarrow> balanced l"
   337 by(simp add: balanced_def)
   338 
   339 lemma balanced_subtreeR: "balanced (Node l x r) \<Longrightarrow> balanced r"
   340 by(simp add: balanced_def)
   341 
   342 lemma balanced_subtrees: "\<lbrakk> balanced t; s \<in> subtrees t \<rbrakk> \<Longrightarrow> balanced s"
   343 using [[simp_depth_limit=1]]
   344 by(induction t arbitrary: s)
   345   (auto simp add: balanced_subtreeL balanced_subtreeR)
   346 
   347 text\<open>Balanced trees have optimal height:\<close>
   348 
   349 lemma balanced_optimal:
   350 fixes t :: "'a tree" and t' :: "'b tree"
   351 assumes "balanced t" "size t \<le> size t'" shows "height t \<le> height t'"
   352 proof (cases "complete t")
   353   case True
   354   have "(2::nat) ^ height t \<le> 2 ^ height t'"
   355   proof -
   356     have "2 ^ height t = size1 t"
   357       using True by (simp add: complete_iff_height size1_if_complete)
   358     also have "\<dots> \<le> size1 t'" using assms(2) by(simp add: size1_def)
   359     also have "\<dots> \<le> 2 ^ height t'" by (rule size1_height)
   360     finally show ?thesis .
   361   qed
   362   thus ?thesis by (simp)
   363 next
   364   case False
   365   have "(2::nat) ^ min_height t < 2 ^ height t'"
   366   proof -
   367     have "(2::nat) ^ min_height t < size1 t"
   368       by(rule min_height_size1_if_incomplete[OF False])
   369     also have "\<dots> \<le> size1 t'" using assms(2) by (simp add: size1_def)
   370     also have "\<dots> \<le> 2 ^ height t'"  by(rule size1_height)
   371     finally have "(2::nat) ^ min_height t < (2::nat) ^ height t'" .
   372     thus ?thesis .
   373   qed
   374   hence *: "min_height t < height t'" by simp
   375   have "min_height t + 1 = height t"
   376     using min_height_le_height[of t] assms(1) False
   377     by (simp add: complete_iff_height balanced_def)
   378   with * show ?thesis by arith
   379 qed
   380 
   381 
   382 subsection \<open>@{const wbalanced}\<close>
   383 
   384 lemma wbalanced_subtrees: "\<lbrakk> wbalanced t; s \<in> subtrees t \<rbrakk> \<Longrightarrow> wbalanced s"
   385 using [[simp_depth_limit=1]] by(induction t arbitrary: s) auto
   386 
   387 
   388 subsection \<open>@{const ipl}\<close>
   389 
   390 text \<open>The internal path length of a tree:\<close>
   391 
   392 lemma ipl_if_complete_int:
   393   "complete t \<Longrightarrow> int(ipl t) = (int(height t) - 2) * 2^(height t) + 2"
   394 apply(induction t)
   395  apply simp
   396 apply simp
   397 apply (simp add: algebra_simps size_if_complete of_nat_diff)
   398 done
   399 
   400 
   401 subsection "List of entries"
   402 
   403 lemma eq_inorder_Nil[simp]: "inorder t = [] \<longleftrightarrow> t = Leaf"
   404 by (cases t) auto
   405 
   406 lemma eq_Nil_inorder[simp]: "[] = inorder t \<longleftrightarrow> t = Leaf"
   407 by (cases t) auto
   408 
   409 lemma set_inorder[simp]: "set (inorder t) = set_tree t"
   410 by (induction t) auto
   411 
   412 lemma set_preorder[simp]: "set (preorder t) = set_tree t"
   413 by (induction t) auto
   414 
   415 lemma set_postorder[simp]: "set (postorder t) = set_tree t"
   416 by (induction t) auto
   417 
   418 lemma length_preorder[simp]: "length (preorder t) = size t"
   419 by (induction t) auto
   420 
   421 lemma length_inorder[simp]: "length (inorder t) = size t"
   422 by (induction t) auto
   423 
   424 lemma length_postorder[simp]: "length (postorder t) = size t"
   425 by (induction t) auto
   426 
   427 lemma preorder_map: "preorder (map_tree f t) = map f (preorder t)"
   428 by (induction t) auto
   429 
   430 lemma inorder_map: "inorder (map_tree f t) = map f (inorder t)"
   431 by (induction t) auto
   432 
   433 lemma postorder_map: "postorder (map_tree f t) = map f (postorder t)"
   434 by (induction t) auto
   435 
   436 lemma inorder2_inorder: "inorder2 t xs = inorder t @ xs"
   437 by (induction t arbitrary: xs) auto
   438 
   439 
   440 subsection \<open>Binary Search Tree\<close>
   441 
   442 lemma (in linorder) bst_eq_if_bst: "bst t \<Longrightarrow> bst_eq t"
   443 by (induction t) (auto)
   444 
   445 lemma (in linorder) bst_eq_imp_sorted: "bst_eq t \<Longrightarrow> sorted (inorder t)"
   446 apply (induction t)
   447  apply(simp)
   448 by (fastforce simp: sorted_append sorted_Cons intro: less_imp_le less_trans)
   449 
   450 lemma (in linorder) distinct_preorder_if_bst: "bst t \<Longrightarrow> distinct (preorder t)"
   451 apply (induction t)
   452  apply simp
   453 apply(fastforce elim: order.asym)
   454 done
   455 
   456 lemma (in linorder) distinct_inorder_if_bst: "bst t \<Longrightarrow> distinct (inorder t)"
   457 apply (induction t)
   458  apply simp
   459 apply(fastforce elim: order.asym)
   460 done
   461 
   462 
   463 subsection \<open>@{const heap}\<close>
   464 
   465 
   466 subsection \<open>@{const mirror}\<close>
   467 
   468 lemma mirror_Leaf[simp]: "mirror t = \<langle>\<rangle> \<longleftrightarrow> t = \<langle>\<rangle>"
   469 by (induction t) simp_all
   470 
   471 lemma Leaf_mirror[simp]: "\<langle>\<rangle> = mirror t \<longleftrightarrow> t = \<langle>\<rangle>"
   472 using mirror_Leaf by fastforce
   473 
   474 lemma size_mirror[simp]: "size(mirror t) = size t"
   475 by (induction t) simp_all
   476 
   477 lemma size1_mirror[simp]: "size1(mirror t) = size1 t"
   478 by (simp add: size1_def)
   479 
   480 lemma height_mirror[simp]: "height(mirror t) = height t"
   481 by (induction t) simp_all
   482 
   483 lemma inorder_mirror: "inorder(mirror t) = rev(inorder t)"
   484 by (induction t) simp_all
   485 
   486 lemma map_mirror: "map_tree f (mirror t) = mirror (map_tree f t)"
   487 by (induction t) simp_all
   488 
   489 lemma mirror_mirror[simp]: "mirror(mirror t) = t"
   490 by (induction t) simp_all
   491 
   492 end