Theory VEBT_Height

(*by Ammer*)
theory VEBT_Height imports VEBT_Definitions Complex_Main
begin

context VEBT_internal begin

section ‹Heights of van Emde Boas Trees›

fun height::"VEBT ⇒ nat" where
  "height (Leaf a b) = 0"|
  "height (Node _ deg treeList summary) = (1+ Max (height ` (insert summary (set treeList))))"

abbreviation "lb x ≡ log 2 x"

lemma setceilmax:  "invar_vebt s m ⟹∀ t ∈ set listy. invar_vebt t n  
     ⟹m = Suc n ⟹(∀ t ∈ set listy. height t = ⌈lb n ⌉ ) ⟹ height s  =  ⌈lb m⌉
      ⟹ Max (height ` (insert s (set listy))) =  ⌈lb m⌉"  
proof(induction listy)
  case Nil
  hence "Max (height ` (insert s(set []))) = height s" by simp
  then show ?case using Nil by simp
next
  case (Cons a list)
  have "Max (height ` insert s (set (a # list))) =
 max (height a) (Max (height ` insert s (set ( list))))"
    by (simp add: insert_commute)
  moreover have "max (height a) (Max (height ` insert s (set ( list)))) = max (height a) ⌈lb m ⌉" 
    using Cons insert_iff list.simps(15) max_def of_nat_max by force
  moreover have " ∀ t ∈ set (a#list). invar_vebt t n " using Cons by simp
  moreover hence "invar_vebt a n" by simp 
  hence "m ≥ n"
    by (simp add: Cons.prems(3))
  hence "lb m ≥ lb n" 
    using deg_not_0 ‹invar_vebt a n› by fastforce
  hence "⌈ lb m⌉ ≥ ⌈ lb n⌉" 
    by (simp add: ceiling_mono)
  moreover hence " max ⌈log 2 n ⌉ ⌈log 2 m ⌉ =  ⌈log 2 m ⌉" by simp
  ultimately show ?case 
    using Cons.prems(4) ‹invar_vebt a n›
    by (metis list.set_intros(1))
qed

lemma log_ceil_idem: 
  assumes"(x::real) ≥ 1" 
  shows "⌈lb x ⌉ = ⌈lb ⌈x⌉⌉" 
proof-
  have "⌈log 2 x ⌉ ≥ 0" 
    by (smt (verit, ccfv_SIG) assms zero_le_ceiling zero_le_log_cancel_iff)
  have " ⌈log 2 x ⌉ -1 < log 2 x ∧log 2 x  ≤ ⌈log 2 x ⌉" 
    by linarith
  moreover hence "2 powr (⌈log 2 x ⌉ -1) < x  ∧ x ≤ 2 powr ( ⌈log 2 x ⌉)" 
    by (smt (verit, ccfv_SIG) assms less_log_iff real_nat_ceiling_ge)
  moreover hence "2 powr ((⌈log 2 x ⌉ -1)) < ⌈x⌉" and " ⌈x⌉ ≤ 2 powr (⌈log 2 x ⌉)" 
     apply linarith 
    using ‹0 ≤ ⌈log 2 x⌉› calculation(2) ceiling_mono powr_int by fastforce 
  moreover hence  " ⌈log 2 x ⌉ -1 < log 2 ⌈ x ⌉ ∧log 2 ⌈x⌉ ≤ ⌈log 2 x ⌉" 
    by (smt (verit, best) assms ceiling_correct less_log_iff)
  ultimately show ?thesis 
    by linarith
qed

lemma heigt_uplog_rel:"invar_vebt t n ⟹ (height t) = ⌈lb n⌉" 
proof(induction t n rule: invar_vebt.induct)
  case (1 a b)
  then show ?case by simp
next
  case (2 treeList n summary m deg)  
  hence "m ≥ n" by simp
  hence "log 2 m ≥ log 2 n" 
    by (simp add: "2.hyps"(3))
  hence "⌈ log 2 m⌉ ≥ ⌈ log 2 n⌉"
    by (simp add: "2.hyps"(3))
  have "Max (height ` (insert summary (set treeList))) = ⌈ log 2 m⌉" 
    by (smt (verit, best) "2.IH"(1) "2.IH"(2) "2.hyps"(3) List.finite_set Max_in empty_is_image finite_imageI finite_insert image_iff insert_iff insert_not_empty)
  hence "height (Node None deg treeList summary) = 1+  ⌈ log 2 m⌉" by simp
  moreover have "1+  ⌈ log 2 m⌉ = ⌈1+ log 2 m⌉" by linarith
  moreover have "1+ log 2 m = log 2 (2*m)" 
    using "2.hyps"(1) deg_not_0 log_mult by force
  moreover hence "⌈1+ log 2 m⌉ = ⌈log 2 (2*m)⌉" by simp
  moreover hence " ⌈log 2 (2*m)⌉  = ⌈log 2 (n+m)⌉" 
    using "2.hyps"(3) by force
  ultimately show ?case 
    using "2.hyps"(4) by metis
next
  case (3 treeList n summary m deg)
  hence 00: "n ≥ 1 ∧ Suc n = m" 
    using set_n_deg_not_0 by blast
  hence 0:"m ≥ n"using 3  by simp
  hence 1:"log 2 m ≥ log 2 n"
    using "3.IH"(1) "3.hyps"(2) set_n_deg_not_0 by fastforce
  hence 2:"⌈ log 2 m⌉ ≥ ⌈ log 2 n⌉"
    by (simp add: ceiling_mono)
  have 3: "Max (height ` (insert summary (set treeList))) = ⌈ log 2 m⌉" 
    using "3.IH"(1) "3.IH"(2) "3.hyps"(3) List.finite_set Max_in empty_is_image
      finite_imageI finite_insert image_iff insert_iff insert_not_empty  "3.hyps"(1) setceilmax by auto
  hence 4:"height (Node None deg treeList summary) = 1+  ⌈ log 2 m⌉" by simp
  have 5:"1+  ⌈ log 2 m⌉ = ⌈1+ log 2 m⌉" by linarith
  have 6:"1+ log 2 m = log 2 (m+m)" 
    using "3.hyps"(1) deg_not_0 log_mult by force
  hence 7:"log 2 (m+n) = 1+log 2 ((n+m) / 2) "
    by (simp add: "3.hyps"(3) log_divide)
  have 8:"log 2 ((n+m) / 2)  = log 2 (n + 1/2)" 
    by (smt (verit, best) "3.hyps"(3) field_sum_of_halves of_nat_Suc of_nat_add)
  have 9 : "⌈ log 2 (n + 1/2) ⌉ = ⌈ log 2 ⌈n + 1/2 ⌉ ⌉" 
    by (smt (verit) "00" field_sum_of_halves log_ceil_idem of_nat_1 of_nat_mono)
  hence 10: " ⌈n + 1/2 ⌉ = m" using 00 by linarith 
  hence 11: "⌈ log 2 (n + 1/2) ⌉  = ⌈ log 2 m ⌉ " using 9 by simp
  hence 12:"⌈ 1+ log 2 (n + 1/2) ⌉  = ⌈1+ log 2 m ⌉" 
    by (smt (verit) ceiling_add_one)
  hence "⌈ log 2 (n + n+1) ⌉  = ⌈ log 2 (m+m) ⌉"
    using "3.hyps"(3) "6" "7" "8" by force
  then show ?case 
    by (metis "12" "3.hyps"(4) "4" "5" "7" "8" add.commute)
next
  case (4 treeList n summary m deg mi ma)
  hence "m ≥ n" by simp
  hence "log 2 m ≥ log 2 n" 
    by (simp add: "4.hyps"(3))
  hence "⌈ log 2 m⌉ ≥ ⌈ log 2 n⌉"
    by (simp add: "4.hyps"(3))
  have "Max (height ` (insert summary (set treeList))) = ⌈ log 2 m⌉" 
    by (smt (verit, best) "4.IH"(1) "4.IH"(2) "4.hyps"(3) List.finite_set Max_in empty_is_image finite_imageI finite_insert image_iff insert_iff insert_not_empty)
  hence "height (Node None deg treeList summary) = 1+  ⌈ log 2 m⌉" by simp
  moreover have "1+  ⌈ log 2 m⌉ = ⌈1+ log 2 m⌉" by linarith
  moreover have "1+ log 2 m = log 2 (2*m)" 
    using "4.hyps"(1) deg_not_0 log_mult by force
  moreover hence "⌈1+ log 2 m⌉ = ⌈log 2 (2*m)⌉" by simp
  moreover hence " ⌈log 2 (2*m)⌉  = ⌈log 2 (n+m)⌉" 
    using "4.hyps"(3) by force
  ultimately show ?case 
    by (metis "4.hyps"(4) height.simps(2))
next
  case (5 treeList n summary m deg mi ma)
  hence 00: "n ≥ 1 ∧ Suc n = m" 
    using set_n_deg_not_0 by blast
  hence 0:"m ≥ n"using 5  by simp
  hence 1:"log 2 m ≥ log 2 n"
    using "5.IH"(1) "5.hyps"(2) set_n_deg_not_0 by fastforce
  hence 2:"⌈ log 2 m⌉ ≥ ⌈ log 2 n⌉"
    by (simp add: ceiling_mono)
  have 3: "Max (height ` (insert summary (set treeList))) = ⌈ log 2 m⌉" 
    using "5.IH"(1) "5.IH"(2) "5.hyps"(3) List.finite_set Max_in empty_is_image
      finite_imageI finite_insert image_iff insert_iff insert_not_empty  "5.hyps"(1) setceilmax by auto
  hence 4:"height (Node None deg treeList summary) = 1+  ⌈ log 2 m⌉" by simp
  have 5:"1+  ⌈ log 2 m⌉ = ⌈1+ log 2 m⌉" by linarith
  have 6:"1+ log 2 m = log 2 (m+m)" 
    using "5.hyps"(1) deg_not_0 log_mult by force
  hence 7:"log 2 (m+n) = 1+log 2 ((n+m) / 2) "
    by (simp add: "5.hyps"(3) log_divide)
  have 8:"log 2 ((n+m) / 2)  = log 2 (n + 1/2)" 
    by (smt (verit, best) "5.hyps"(3) field_sum_of_halves of_nat_Suc of_nat_add)
  have 9 : "⌈ log 2 (n + 1/2) ⌉ = ⌈ log 2 ⌈n + 1/2 ⌉ ⌉" 
    by (smt (verit) "00" field_sum_of_halves log_ceil_idem of_nat_1 of_nat_mono)
  hence 10: " ⌈n + 1/2 ⌉ = m" using 00 by linarith 
  hence 11: "⌈ log 2 (n + 1/2) ⌉  = ⌈ log 2 m ⌉ " using 9 by simp
  hence 12:"⌈ 1+ log 2 (n + 1/2) ⌉  = ⌈1+ log 2 m ⌉" 
    by (smt (verit) ceiling_add_one)
  hence "⌈ log 2 (n + n+1) ⌉  = ⌈ log 2 (m+m) ⌉"
    using "5.hyps"(3) "6" "7" "8" by force
  then show ?case
    using "4" "5" "5.hyps"(3) "5.hyps"(4) "6" by force
qed

lemma two_powr_height_bound_deg: 
  assumes "invar_vebt t n " 
  shows " 2^(height t) ≤ 2*(n::nat)" 
proof-
  have " (height t) = ⌈ log 2 n⌉" 
    by (simp add: assms heigt_uplog_rel)
  moreover  have "⌈ log 2 n⌉ ≤ log 2 n +1" by simp
  moreover hence "2 powr ⌈ log 2 n⌉ ≤ 2 powr  (log 2 n +1)" by simp
  moreover have " 2 powr  (log 2 n +1) = 2 powr 1 * 2 powr  (log 2 n)"
    by (simp add: powr_add)
  moreover hence " 2 powr  (log 2 n +1) = 2 * n" 
    using assms deg_not_0 by force
  ultimately show ?thesis 
    by (metis linorder_not_less not_one_le_zero of_int_0 of_int_less_iff of_int_numeral of_int_of_nat_eq of_nat_le_iff one_add_one order_less_le powr_realpow real_of_nat_eq_numeral_power_cancel_iff zle_add1_eq_le)
qed

text ‹Main Theorem›

theorem height_double_log_univ_size: 
  assumes "u = 2^deg" and "invar_vebt t deg " 
  shows "height t ≤ 1 + lb (lb u)" 
proof-
  have "(height t) = ⌈lb deg⌉" 
    by (simp add: assms(2) heigt_uplog_rel)
  have "2^(height t) ≤ 2 *  deg" using assms(2)  two_powr_height_bound_deg[of t deg] 
    by (meson dual_order.eq_iff dual_order.trans self_le_ge2_pow)
  hence "height t ≤ 1 + lb deg" 
    using ‹int (height t) = ⌈lb (real deg)⌉› by linarith
  hence "height t ≤ 1 + lb (lb u)" using assms by simp
  thus ?thesis by simp
qed

lemma height_compose_list:  " t∈ set treeList ⟹
 Max (height ` (insert summary (set treeList)))  ≥  height t"
  apply(induction treeList) apply simp 
  by (meson List.finite_set Max_ge finite_imageI finite_insert image_eqI subsetD subset_insertI)

lemma height_compose_child:  " t∈ set treeList ⟹
 height (Node info deg treeList summary)  ≥ 1+  height t" by simp

lemma height_compose_summary: " height (Node info deg treeList summary)  ≥ 1+  height summary" by simp

lemma  height_i_max: " i < length x13 ⟹
       height (x13 ! i) ≤ max foo  (Max (height ` set x13))"
  by (meson List.finite_set Max_ge finite_imageI max.coboundedI2 nth_mem rev_image_eqI)

lemma max_ins_scaled: " n* height x14 ≤ m + n* Max (insert (height x14) (height ` set x13))"
  by (meson List.finite_set Max_ge finite_imageI finite_insert insertI1 mult_le_mono2 trans_le_add2)

lemma max_idx_list: 
  assumes "i < length x13 "
  shows " n * height (x13 !i) ≤ Suc (Suc (n * max (height x14) (Max (height ` set x13))))" 
  by (metis assms height_i_max less_Suc_eq mult_le_mono2 nat_less_le)

end
end