src/HOL/Library/Tree.thy
author haftmann
Fri Mar 22 19:18:08 2019 +0000 (3 months ago)
changeset 69946 494934c30f38
parent 69655 2b56cbb02e8a
permissions -rw-r--r--
improved code equations taken over from AFP
     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" ("value": 'a) "'a tree" ("(1\<langle>_,/ _,/ _\<rangle>)")
    13 datatype_compat tree
    14 
    15 primrec left :: "'a tree \<Rightarrow> 'a tree" where
    16 "left (Node l v r) = l" |
    17 "left Leaf = Leaf"
    18 
    19 primrec right :: "'a tree \<Rightarrow> 'a tree" where
    20 "right (Node l v r) = r" |
    21 "right Leaf = Leaf"
    22 
    23 text\<open>Counting the number of leaves rather than nodes:\<close>
    24 
    25 fun size1 :: "'a tree \<Rightarrow> nat" where
    26 "size1 \<langle>\<rangle> = 1" |
    27 "size1 \<langle>l, x, r\<rangle> = size1 l + size1 r"
    28 
    29 fun subtrees :: "'a tree \<Rightarrow> 'a tree set" where
    30 "subtrees \<langle>\<rangle> = {\<langle>\<rangle>}" |
    31 "subtrees (\<langle>l, a, r\<rangle>) = insert \<langle>l, a, r\<rangle> (subtrees l \<union> subtrees r)"
    32 
    33 fun mirror :: "'a tree \<Rightarrow> 'a tree" where
    34 "mirror \<langle>\<rangle> = Leaf" |
    35 "mirror \<langle>l,x,r\<rangle> = \<langle>mirror r, x, mirror l\<rangle>"
    36 
    37 class height = fixes height :: "'a \<Rightarrow> nat"
    38 
    39 instantiation tree :: (type)height
    40 begin
    41 
    42 fun height_tree :: "'a tree => nat" where
    43 "height Leaf = 0" |
    44 "height (Node l a r) = max (height l) (height r) + 1"
    45 
    46 instance ..
    47 
    48 end
    49 
    50 fun min_height :: "'a tree \<Rightarrow> nat" where
    51 "min_height Leaf = 0" |
    52 "min_height (Node l _ r) = min (min_height l) (min_height r) + 1"
    53 
    54 fun complete :: "'a tree \<Rightarrow> bool" where
    55 "complete Leaf = True" |
    56 "complete (Node l x r) = (complete l \<and> complete r \<and> height l = height r)"
    57 
    58 definition balanced :: "'a tree \<Rightarrow> bool" where
    59 "balanced t = (height t - min_height t \<le> 1)"
    60 
    61 text \<open>Weight balanced:\<close>
    62 fun wbalanced :: "'a tree \<Rightarrow> bool" where
    63 "wbalanced Leaf = True" |
    64 "wbalanced (Node l x r) = (abs(int(size l) - int(size r)) \<le> 1 \<and> wbalanced l \<and> wbalanced r)"
    65 
    66 text \<open>Internal path length:\<close>
    67 fun ipl :: "'a tree \<Rightarrow> nat" where
    68 "ipl Leaf = 0 " |
    69 "ipl (Node l _ r) = ipl l + size l + ipl r + size r"
    70 
    71 fun preorder :: "'a tree \<Rightarrow> 'a list" where
    72 "preorder \<langle>\<rangle> = []" |
    73 "preorder \<langle>l, x, r\<rangle> = x # preorder l @ preorder r"
    74 
    75 fun inorder :: "'a tree \<Rightarrow> 'a list" where
    76 "inorder \<langle>\<rangle> = []" |
    77 "inorder \<langle>l, x, r\<rangle> = inorder l @ [x] @ inorder r"
    78 
    79 text\<open>A linear version avoiding append:\<close>
    80 fun inorder2 :: "'a tree \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    81 "inorder2 \<langle>\<rangle> xs = xs" |
    82 "inorder2 \<langle>l, x, r\<rangle> xs = inorder2 l (x # inorder2 r xs)"
    83 
    84 fun postorder :: "'a tree \<Rightarrow> 'a list" where
    85 "postorder \<langle>\<rangle> = []" |
    86 "postorder \<langle>l, x, r\<rangle> = postorder l @ postorder r @ [x]"
    87 
    88 text\<open>Binary Search Tree:\<close>
    89 fun bst_wrt :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a tree \<Rightarrow> bool" where
    90 "bst_wrt P \<langle>\<rangle> \<longleftrightarrow> True" |
    91 "bst_wrt P \<langle>l, a, r\<rangle> \<longleftrightarrow>
    92  bst_wrt P l \<and> bst_wrt P r \<and> (\<forall>x\<in>set_tree l. P x a) \<and> (\<forall>x\<in>set_tree r. P a x)"
    93 
    94 abbreviation bst :: "('a::linorder) tree \<Rightarrow> bool" where
    95 "bst \<equiv> bst_wrt (<)"
    96 
    97 fun (in linorder) heap :: "'a tree \<Rightarrow> bool" where
    98 "heap Leaf = True" |
    99 "heap (Node l m r) =
   100   (heap l \<and> heap r \<and> (\<forall>x \<in> set_tree l \<union> set_tree r. m \<le> x))"
   101 
   102 
   103 subsection \<open>\<^const>\<open>map_tree\<close>\<close>
   104 
   105 lemma eq_map_tree_Leaf[simp]: "map_tree f t = Leaf \<longleftrightarrow> t = Leaf"
   106 by (rule tree.map_disc_iff)
   107 
   108 lemma eq_Leaf_map_tree[simp]: "Leaf = map_tree f t \<longleftrightarrow> t = Leaf"
   109 by (cases t) auto
   110 
   111 
   112 subsection \<open>\<^const>\<open>size\<close>\<close>
   113 
   114 lemma size1_size: "size1 t = size t + 1"
   115 by (induction t) simp_all
   116 
   117 lemma size1_ge0[simp]: "0 < size1 t"
   118 by (simp add: size1_size)
   119 
   120 lemma eq_size_0[simp]: "size t = 0 \<longleftrightarrow> t = Leaf"
   121 by(cases t) auto
   122 
   123 lemma eq_0_size[simp]: "0 = size t \<longleftrightarrow> t = Leaf"
   124 by(cases t) auto
   125 
   126 lemma neq_Leaf_iff: "(t \<noteq> \<langle>\<rangle>) = (\<exists>l a r. t = \<langle>l, a, r\<rangle>)"
   127 by (cases t) auto
   128 
   129 lemma size_map_tree[simp]: "size (map_tree f t) = size t"
   130 by (induction t) auto
   131 
   132 lemma size1_map_tree[simp]: "size1 (map_tree f t) = size1 t"
   133 by (simp add: size1_size)
   134 
   135 
   136 subsection \<open>\<^const>\<open>set_tree\<close>\<close>
   137 
   138 lemma eq_set_tree_empty[simp]: "set_tree t = {} \<longleftrightarrow> t = Leaf"
   139 by (cases t) auto
   140 
   141 lemma eq_empty_set_tree[simp]: "{} = set_tree t \<longleftrightarrow> t = Leaf"
   142 by (cases t) auto
   143 
   144 lemma finite_set_tree[simp]: "finite(set_tree t)"
   145 by(induction t) auto
   146 
   147 
   148 subsection \<open>\<^const>\<open>subtrees\<close>\<close>
   149 
   150 lemma neq_subtrees_empty[simp]: "subtrees t \<noteq> {}"
   151 by (cases t)(auto)
   152 
   153 lemma neq_empty_subtrees[simp]: "{} \<noteq> subtrees t"
   154 by (cases t)(auto)
   155 
   156 lemma set_treeE: "a \<in> set_tree t \<Longrightarrow> \<exists>l r. \<langle>l, a, r\<rangle> \<in> subtrees t"
   157 by (induction t)(auto)
   158 
   159 lemma Node_notin_subtrees_if[simp]: "a \<notin> set_tree t \<Longrightarrow> Node l a r \<notin> subtrees t"
   160 by (induction t) auto
   161 
   162 lemma in_set_tree_if: "\<langle>l, a, r\<rangle> \<in> subtrees t \<Longrightarrow> a \<in> set_tree t"
   163 by (metis Node_notin_subtrees_if)
   164 
   165 
   166 subsection \<open>\<^const>\<open>height\<close> and \<^const>\<open>min_height\<close>\<close>
   167 
   168 lemma eq_height_0[simp]: "height t = 0 \<longleftrightarrow> t = Leaf"
   169 by(cases t) auto
   170 
   171 lemma eq_0_height[simp]: "0 = height t \<longleftrightarrow> t = Leaf"
   172 by(cases t) auto
   173 
   174 lemma height_map_tree[simp]: "height (map_tree f t) = height t"
   175 by (induction t) auto
   176 
   177 lemma height_le_size_tree: "height t \<le> size (t::'a tree)"
   178 by (induction t) auto
   179 
   180 lemma size1_height: "size1 t \<le> 2 ^ height (t::'a tree)"
   181 proof(induction t)
   182   case (Node l a r)
   183   show ?case
   184   proof (cases "height l \<le> height r")
   185     case True
   186     have "size1(Node l a r) = size1 l + size1 r" by simp
   187     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r" using Node.IH by arith
   188     also have "\<dots> \<le> 2 ^ height r + 2 ^ height r" using True by simp
   189     also have "\<dots> = 2 ^ height (Node l a r)"
   190       using True by (auto simp: max_def mult_2)
   191     finally show ?thesis .
   192   next
   193     case False
   194     have "size1(Node l a r) = size1 l + size1 r" by simp
   195     also have "\<dots> \<le> 2 ^ height l + 2 ^ height r" using Node.IH by arith
   196     also have "\<dots> \<le> 2 ^ height l + 2 ^ height l" using False by simp
   197     finally show ?thesis using False by (auto simp: max_def mult_2)
   198   qed
   199 qed simp
   200 
   201 corollary size_height: "size t \<le> 2 ^ height (t::'a tree) - 1"
   202 using size1_height[of t, unfolded size1_size] by(arith)
   203 
   204 lemma height_subtrees: "s \<in> subtrees t \<Longrightarrow> height s \<le> height t"
   205 by (induction t) auto
   206 
   207 
   208 lemma min_height_le_height: "min_height t \<le> height t"
   209 by(induction t) auto
   210 
   211 lemma min_height_map_tree[simp]: "min_height (map_tree f t) = min_height t"
   212 by (induction t) auto
   213 
   214 lemma min_height_size1: "2 ^ min_height t \<le> size1 t"
   215 proof(induction t)
   216   case (Node l a r)
   217   have "(2::nat) ^ min_height (Node l a r) \<le> 2 ^ min_height l + 2 ^ min_height r"
   218     by (simp add: min_def)
   219   also have "\<dots> \<le> size1(Node l a r)" using Node.IH by simp
   220   finally show ?case .
   221 qed simp
   222 
   223 
   224 subsection \<open>\<^const>\<open>complete\<close>\<close>
   225 
   226 lemma complete_iff_height: "complete t \<longleftrightarrow> (min_height t = height t)"
   227 apply(induction t)
   228  apply simp
   229 apply (simp add: min_def max_def)
   230 by (metis le_antisym le_trans min_height_le_height)
   231 
   232 lemma size1_if_complete: "complete t \<Longrightarrow> size1 t = 2 ^ height t"
   233 by (induction t) auto
   234 
   235 lemma size_if_complete: "complete t \<Longrightarrow> size t = 2 ^ height t - 1"
   236 using size1_if_complete[simplified size1_size] by fastforce
   237 
   238 lemma size1_height_if_incomplete:
   239   "\<not> complete t \<Longrightarrow> size1 t < 2 ^ height t"
   240 proof(induction t)
   241   case Leaf thus ?case by simp
   242 next
   243   case (Node l x r)
   244   have 1: ?case if h: "height l < height r"
   245     using h size1_height[of l] size1_height[of r] power_strict_increasing[OF h, of "2::nat"]
   246     by(auto simp: max_def simp del: power_strict_increasing_iff)
   247   have 2: ?case if h: "height l > height r"
   248     using h size1_height[of l] size1_height[of r] power_strict_increasing[OF h, of "2::nat"]
   249     by(auto simp: max_def simp del: power_strict_increasing_iff)
   250   have 3: ?case if h: "height l = height r" and c: "\<not> complete l"
   251     using h size1_height[of r] Node.IH(1)[OF c] by(simp)
   252   have 4: ?case if h: "height l = height r" and c: "\<not> complete r"
   253     using h size1_height[of l] Node.IH(2)[OF c] by(simp)
   254   from 1 2 3 4 Node.prems show ?case apply (simp add: max_def) by linarith
   255 qed
   256 
   257 lemma complete_iff_min_height: "complete t \<longleftrightarrow> (height t = min_height t)"
   258 by(auto simp add: complete_iff_height)
   259 
   260 lemma min_height_size1_if_incomplete:
   261   "\<not> complete t \<Longrightarrow> 2 ^ min_height t < size1 t"
   262 proof(induction t)
   263   case Leaf thus ?case by simp
   264 next
   265   case (Node l x r)
   266   have 1: ?case if h: "min_height l < min_height r"
   267     using h min_height_size1[of l] min_height_size1[of r] power_strict_increasing[OF h, of "2::nat"]
   268     by(auto simp: max_def simp del: power_strict_increasing_iff)
   269   have 2: ?case if h: "min_height l > min_height r"
   270     using h min_height_size1[of l] min_height_size1[of r] power_strict_increasing[OF h, of "2::nat"]
   271     by(auto simp: max_def simp del: power_strict_increasing_iff)
   272   have 3: ?case if h: "min_height l = min_height r" and c: "\<not> complete l"
   273     using h min_height_size1[of r] Node.IH(1)[OF c] by(simp add: complete_iff_min_height)
   274   have 4: ?case if h: "min_height l = min_height r" and c: "\<not> complete r"
   275     using h min_height_size1[of l] Node.IH(2)[OF c] by(simp add: complete_iff_min_height)
   276   from 1 2 3 4 Node.prems show ?case
   277     by (fastforce simp: complete_iff_min_height[THEN iffD1])
   278 qed
   279 
   280 lemma complete_if_size1_height: "size1 t = 2 ^ height t \<Longrightarrow> complete t"
   281 using  size1_height_if_incomplete by fastforce
   282 
   283 lemma complete_if_size1_min_height: "size1 t = 2 ^ min_height t \<Longrightarrow> complete t"
   284 using min_height_size1_if_incomplete by fastforce
   285 
   286 lemma complete_iff_size1: "complete t \<longleftrightarrow> size1 t = 2 ^ height t"
   287 using complete_if_size1_height size1_if_complete by blast
   288 
   289 
   290 subsection \<open>\<^const>\<open>balanced\<close>\<close>
   291 
   292 lemma balanced_subtreeL: "balanced (Node l x r) \<Longrightarrow> balanced l"
   293 by(simp add: balanced_def)
   294 
   295 lemma balanced_subtreeR: "balanced (Node l x r) \<Longrightarrow> balanced r"
   296 by(simp add: balanced_def)
   297 
   298 lemma balanced_subtrees: "\<lbrakk> balanced t; s \<in> subtrees t \<rbrakk> \<Longrightarrow> balanced s"
   299 using [[simp_depth_limit=1]]
   300 by(induction t arbitrary: s)
   301   (auto simp add: balanced_subtreeL balanced_subtreeR)
   302 
   303 text\<open>Balanced trees have optimal height:\<close>
   304 
   305 lemma balanced_optimal:
   306 fixes t :: "'a tree" and t' :: "'b tree"
   307 assumes "balanced t" "size t \<le> size t'" shows "height t \<le> height t'"
   308 proof (cases "complete t")
   309   case True
   310   have "(2::nat) ^ height t \<le> 2 ^ height t'"
   311   proof -
   312     have "2 ^ height t = size1 t"
   313       using True by (simp add: size1_if_complete)
   314     also have "\<dots> \<le> size1 t'" using assms(2) by(simp add: size1_size)
   315     also have "\<dots> \<le> 2 ^ height t'" by (rule size1_height)
   316     finally show ?thesis .
   317   qed
   318   thus ?thesis by (simp)
   319 next
   320   case False
   321   have "(2::nat) ^ min_height t < 2 ^ height t'"
   322   proof -
   323     have "(2::nat) ^ min_height t < size1 t"
   324       by(rule min_height_size1_if_incomplete[OF False])
   325     also have "\<dots> \<le> size1 t'" using assms(2) by (simp add: size1_size)
   326     also have "\<dots> \<le> 2 ^ height t'"  by(rule size1_height)
   327     finally have "(2::nat) ^ min_height t < (2::nat) ^ height t'" .
   328     thus ?thesis .
   329   qed
   330   hence *: "min_height t < height t'" by simp
   331   have "min_height t + 1 = height t"
   332     using min_height_le_height[of t] assms(1) False
   333     by (simp add: complete_iff_height balanced_def)
   334   with * show ?thesis by arith
   335 qed
   336 
   337 
   338 subsection \<open>\<^const>\<open>wbalanced\<close>\<close>
   339 
   340 lemma wbalanced_subtrees: "\<lbrakk> wbalanced t; s \<in> subtrees t \<rbrakk> \<Longrightarrow> wbalanced s"
   341 using [[simp_depth_limit=1]] by(induction t arbitrary: s) auto
   342 
   343 
   344 subsection \<open>\<^const>\<open>ipl\<close>\<close>
   345 
   346 text \<open>The internal path length of a tree:\<close>
   347 
   348 lemma ipl_if_complete_int:
   349   "complete t \<Longrightarrow> int(ipl t) = (int(height t) - 2) * 2^(height t) + 2"
   350 apply(induction t)
   351  apply simp
   352 apply simp
   353 apply (simp add: algebra_simps size_if_complete of_nat_diff)
   354 done
   355 
   356 
   357 subsection "List of entries"
   358 
   359 lemma eq_inorder_Nil[simp]: "inorder t = [] \<longleftrightarrow> t = Leaf"
   360 by (cases t) auto
   361 
   362 lemma eq_Nil_inorder[simp]: "[] = inorder t \<longleftrightarrow> t = Leaf"
   363 by (cases t) auto
   364 
   365 lemma set_inorder[simp]: "set (inorder t) = set_tree t"
   366 by (induction t) auto
   367 
   368 lemma set_preorder[simp]: "set (preorder t) = set_tree t"
   369 by (induction t) auto
   370 
   371 lemma set_postorder[simp]: "set (postorder t) = set_tree t"
   372 by (induction t) auto
   373 
   374 lemma length_preorder[simp]: "length (preorder t) = size t"
   375 by (induction t) auto
   376 
   377 lemma length_inorder[simp]: "length (inorder t) = size t"
   378 by (induction t) auto
   379 
   380 lemma length_postorder[simp]: "length (postorder t) = size t"
   381 by (induction t) auto
   382 
   383 lemma preorder_map: "preorder (map_tree f t) = map f (preorder t)"
   384 by (induction t) auto
   385 
   386 lemma inorder_map: "inorder (map_tree f t) = map f (inorder t)"
   387 by (induction t) auto
   388 
   389 lemma postorder_map: "postorder (map_tree f t) = map f (postorder t)"
   390 by (induction t) auto
   391 
   392 lemma inorder2_inorder: "inorder2 t xs = inorder t @ xs"
   393 by (induction t arbitrary: xs) auto
   394 
   395 
   396 subsection \<open>Binary Search Tree\<close>
   397 
   398 lemma bst_wrt_mono: "(\<And>x y. P x y \<Longrightarrow> Q x y) \<Longrightarrow> bst_wrt P t \<Longrightarrow> bst_wrt Q t"
   399 by (induction t) (auto)
   400 
   401 lemma bst_wrt_le_if_bst: "bst t \<Longrightarrow> bst_wrt (\<le>) t"
   402 using bst_wrt_mono less_imp_le by blast
   403 
   404 lemma bst_wrt_le_iff_sorted: "bst_wrt (\<le>) t \<longleftrightarrow> sorted (inorder t)"
   405 apply (induction t)
   406  apply(simp)
   407 by (fastforce simp: sorted_append intro: less_imp_le less_trans)
   408 
   409 lemma bst_iff_sorted_wrt_less: "bst t \<longleftrightarrow> sorted_wrt (<) (inorder t)"
   410 apply (induction t)
   411  apply simp
   412 apply (fastforce simp: sorted_wrt_append)
   413 done
   414 
   415 
   416 subsection \<open>\<^const>\<open>heap\<close>\<close>
   417 
   418 
   419 subsection \<open>\<^const>\<open>mirror\<close>\<close>
   420 
   421 lemma mirror_Leaf[simp]: "mirror t = \<langle>\<rangle> \<longleftrightarrow> t = \<langle>\<rangle>"
   422 by (induction t) simp_all
   423 
   424 lemma Leaf_mirror[simp]: "\<langle>\<rangle> = mirror t \<longleftrightarrow> t = \<langle>\<rangle>"
   425 using mirror_Leaf by fastforce
   426 
   427 lemma size_mirror[simp]: "size(mirror t) = size t"
   428 by (induction t) simp_all
   429 
   430 lemma size1_mirror[simp]: "size1(mirror t) = size1 t"
   431 by (simp add: size1_size)
   432 
   433 lemma height_mirror[simp]: "height(mirror t) = height t"
   434 by (induction t) simp_all
   435 
   436 lemma min_height_mirror [simp]: "min_height (mirror t) = min_height t"
   437 by (induction t) simp_all  
   438 
   439 lemma ipl_mirror [simp]: "ipl (mirror t) = ipl t"
   440 by (induction t) simp_all
   441 
   442 lemma inorder_mirror: "inorder(mirror t) = rev(inorder t)"
   443 by (induction t) simp_all
   444 
   445 lemma map_mirror: "map_tree f (mirror t) = mirror (map_tree f t)"
   446 by (induction t) simp_all
   447 
   448 lemma mirror_mirror[simp]: "mirror(mirror t) = t"
   449 by (induction t) simp_all
   450 
   451 end