(*  Title:      RealPower/Log.thy
    Authors:    Jacques D. Fleuriot
                University of Edinburgh, 2021
*)

section\<open>Real Logarithms (Redefined)\<close>

theory Log
imports RealPower
begin

text\<open>We can now directly define real logarithm of @{term x} to base @{term a}.\<close>

definition
    Log  :: "[real,real] \<Rightarrow> real" where
   "Log a x = (THE y. a pow\<^sub>\<real> y = x)"

lemma IVT_simple:
  "\<lbrakk>f (a::real) \<le> (y::real); y \<le> f b; a \<le> b;
    \<forall>x. a \<le> x \<and> x \<le> b \<longrightarrow> isCont f x\<rbrakk>
   \<Longrightarrow> \<exists>x. f x = y"
by (frule IVT [of f]) auto

lemma inj_on_powreal:
   "0 < a \<Longrightarrow> a \<noteq> 1 \<Longrightarrow> inj_on (\<lambda>x. a pow\<^sub>\<real> x) UNIV"
by (auto simp add: inj_on_def)

lemma LIMSEQ_powreal_minus_nat:
  "a > 1 \<Longrightarrow> (\<lambda>n. a pow\<^sub>\<real> (-real n)) \<longlonglongrightarrow> 0"
by (simp add: powreal_minus powreal_power_eq
        LIMSEQ_inverse_realpow_zero)

lemma LIMSEQ_less_Ex:
   "\<lbrakk> X \<longlonglongrightarrow> (x::real); x < y \<rbrakk> \<Longrightarrow> \<exists>n. X n < y"
  by (meson LIMSEQ_le_const not_less)

lemma powreal_IVT_upper_lemma:
  assumes "a > (1::real)" and "x > 0"
  shows "\<exists>n::nat. a pow\<^sub>\<real> (-real n) < x"
proof -
  have "(\<lambda>n. a pow\<^sub>\<real> - real n) \<longlonglongrightarrow> 0"
    by (simp add: LIMSEQ_powreal_minus_nat assms(1))
  then show ?thesis
    using LIMSEQ_less_Ex assms(2) by blast
qed

lemma powreal_IVT_lower_lemma:
  assumes "a > (1::real)"
  and "x > 0"
  shows "\<exists>n::nat. x < a pow\<^sub>\<real> (real n)"
proof -
  have invx0: "0 < inverse x"
    by (simp add: assms(2))
  then have "\<exists>n. a pow\<^sub>\<real> - real n < inverse x"
    using assms(1) powreal_IVT_upper_lemma by blast
  then show ?thesis
    using assms(1)
    by (auto dest: inverse_less_imp_less
         simp add: powreal_minus powreal_gt_zero )
qed

lemma powreal_surj:
  assumes "a > 1"
  and "x > 0"
  shows "\<exists>y. a pow\<^sub>\<real> y = x"
proof -
  obtain n where "a pow\<^sub>\<real> - real n < x"
    using assms powreal_IVT_upper_lemma by blast
  moreover obtain na where "x < a pow\<^sub>\<real> real na"
    using assms powreal_IVT_lower_lemma by blast
  moreover have "\<forall>x. - real n \<le> x \<and> x \<le> real na \<longrightarrow> isCont ((pow\<^sub>\<real>) a) x"
    using assms(1) isCont_powreal_exponent_gt_one by blast
  ultimately show ?thesis
    using IVT_simple [of _ "-real n" _ "real na"] by force
qed

lemma powreal_surj2:
    "\<lbrakk> 0 < a; a < 1; x > 0 \<rbrakk> \<Longrightarrow> \<exists>y. a pow\<^sub>\<real> y = x"
  using powreal_minus_base_ge_one powreal_surj real_inverse_gt_one_lemma
  by blast

lemma powreal_ex1_eq:
  assumes "a > 0"
  and "a \<noteq> 1"
  and "x > 0"
  shows "\<exists>! y. a pow\<^sub>\<real> y = x"
proof (cases "a < 1")
  case True
  then show ?thesis
    using assms powreal_inject powreal_surj2 by blast
next
  case False
  then show ?thesis
    using assms(2) assms(3) powreal_surj by auto
qed

lemma powreal_Log_cancel [simp]:
   "\<lbrakk> a > 0; a \<noteq> 1; x > 0 \<rbrakk> \<Longrightarrow> a pow\<^sub>\<real> (Log a x) = x"
by (auto intro: the1I2 [OF powreal_ex1_eq] simp add: Log_def)

lemma Log_powreal_cancel [simp]:
  "\<lbrakk> 0 < a; a \<noteq> 1 \<rbrakk> \<Longrightarrow> Log a (a pow\<^sub>\<real> y) = y"
by (metis powreal_ex1_eq powreal_gt_zero powreal_Log_cancel)

lemma Log_mult:
     "\<lbrakk> 0 < a; a \<noteq> 1; 0 < x; 0 < y \<rbrakk>
      \<Longrightarrow> Log a (x * y) = Log a x + Log a y"
  by (metis Log_powreal_cancel powreal_Log_cancel powreal_add)

lemma Log_one [simp]: "\<lbrakk> 0 < a; a \<noteq> 1 \<rbrakk> \<Longrightarrow> Log a 1 = 0"
by (metis Log_powreal_cancel powreal_zero_eq_one)

lemma Log_eq_one [simp]: "\<lbrakk> 0 < a; a \<noteq> 1 \<rbrakk> \<Longrightarrow> Log a a = 1"
  using powreal_inject by fastforce

lemma Log_inverse:
  "\<lbrakk> a > 0; a \<noteq> 1; x > 0 \<rbrakk> \<Longrightarrow> Log a (inverse x) = - Log a x"
by (metis Log_powreal_cancel powreal_Log_cancel powreal_minus)

lemma Log_divide:
  "\<lbrakk> 0 < a; a \<noteq> 1; 0 < x; 0 < y \<rbrakk>
   \<Longrightarrow> Log a (x/y) = Log a x - Log a y"
  by (metis Log_inverse Log_mult divide_real_def
       inverse_positive_iff_positive minus_real_def)

lemma Log_less_cancel_iff [simp]:
  assumes "1 < a"
  and "0 < x"
  and "0 < y"
shows "(Log a x < Log a y) = (x < y)"
proof
  assume "Log a x < Log a y"
  then show "x < y" using powreal_Log_cancel assms powreal_less_cancel_iff
    by (metis less_irrefl real_inverse_bet_one_one_lemma
          inverse_positive_iff_positive)
next
  assume "x < y"
  then show "Log a x < Log a y"
    using assms(1) assms(2) powreal_less_cancel_iff by fastforce
qed

lemma Log_inj: assumes "1 < b" shows "inj_on (Log b) {0 <..}"
proof (rule inj_onI, simp)
  fix x y assume pos: "0 < x" "0 < y" and *: "Log b x = Log b y"
  show "x = y"
  proof (cases rule: linorder_cases)
    assume "x < y" hence "Log b x < Log b y"
      using Log_less_cancel_iff[OF \<open>1 < b\<close>] pos by simp
    thus ?thesis using * by simp
  next
    assume "y < x" hence "Log b y < Log b x"
      using Log_less_cancel_iff[OF \<open>1 < b\<close>] pos by simp
    thus ?thesis using * by simp
  qed simp
qed

lemma Log_le_cancel_iff [simp]:
     "\<lbrakk> 1 < a; 0 < x; 0 < y \<rbrakk> \<Longrightarrow> (Log a x \<le> Log a y) = (x \<le> y)"
by (simp add: linorder_not_less [symmetric])

lemma zero_less_Log_cancel_iff [simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> 0 < Log a x \<longleftrightarrow> 1 < x"
  using Log_less_cancel_iff[of a 1 x] by simp

lemma zero_le_Log_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> 0 \<le> Log a x \<longleftrightarrow> 1 \<le> x"
  using Log_le_cancel_iff[of a 1 x] by simp

lemma Log_less_zero_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> Log a x < 0 \<longleftrightarrow> x < 1"
  using Log_less_cancel_iff[of a x 1] by simp

lemma Log_le_zero_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> Log a x \<le> 0 \<longleftrightarrow> x \<le> 1"
  using Log_le_cancel_iff[of a x 1] by simp

lemma one_less_Log_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> 1 < Log a x \<longleftrightarrow> a < x"
  using Log_less_cancel_iff[of a a x] by simp

lemma one_le_Log_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> 1 \<le> Log a x \<longleftrightarrow> a \<le> x"
  using Log_le_cancel_iff[of a a x] by simp

lemma Log_less_one_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> Log a x < 1 \<longleftrightarrow> x < a"
  using Log_less_cancel_iff[of a x a] by simp

lemma Log_le_one_cancel_iff[simp]:
  "1 < a \<Longrightarrow> 0 < x \<Longrightarrow> Log a x \<le> 1 \<longleftrightarrow> x \<le> a"
  using Log_le_cancel_iff[of a x a] by simp

lemma Log_powreal:
  assumes "0 < x"
  and "1 < b"
  and "b \<noteq> 1"
shows "Log b (x pow\<^sub>\<real> y) = y * Log b x"
proof -
  have "b pow\<^sub>\<real> (Log b x * y) = x pow\<^sub>\<real> y"
    using assms powreal_mult [symmetric] by simp
  moreover have "0 < x pow\<^sub>\<real> y"
    by (simp add: assms(1) powreal_gt_zero)
  ultimately have "b pow\<^sub>\<real> (y * Log b x) = b pow\<^sub>\<real> Log b (x pow\<^sub>\<real> y)"
    using powreal_Log_cancel assms powreal_Log_cancel
    by (simp add: mult.commute)
  then show ?thesis
    using assms(2) powreal_inject_exp1 by blast
qed

lemma Log_nat_power:
  assumes "0 < x"
  and "1 < b" and "b \<noteq> 1"
  shows " Log b (x ^ n) = real n * Log b x"
proof -
  have "Log b (x pow\<^sub>\<real> real n) = real n * Log b x"
    by (simp add: Log_powreal assms)
  then show ?thesis
    by (simp add: assms(1) powreal_power_eq)
qed

end


theory tp2
imports Main
begin

(* 1.1 : Construction des ensembles *)

fun member :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" where
  "member _ [] = False" |
  "member x (t#q) = ((x = t) \<or> (member x q))"

fun isSet :: "'a list \<Rightarrow> bool" where
  "isSet [] = True"
| "isSet (t#q) = ((\<not>(member t q)) \<and> (isSet q))"

fun clean :: "'a list \<Rightarrow> 'a list" where
  "clean [] = []"
| "clean (t#q) = (if (member t q) then (clean q) else (t#(clean q)))"

lemma member_clean: "(member x l) = (member x (clean l))"
  apply (induct l)
   apply auto
  done

lemma isSet_clean: "isSet (clean l)"
  apply (induct l)
   apply simp
   using member_clean by fastforce

(* 1.2 : Suppression d'un élément *)

fun delete :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
  "delete x [] = []"
| "delete x (t#q) = (if (x=t) then (q) else (t#(delete x q)))"

lemma member_delete1: "(isSet l) \<longrightarrow> (\<not>(member x (delete x l)))"
  apply (induct l)
   apply auto
  done

lemma member_delete2: "(isSet l) \<longrightarrow> ((y \<noteq> x) \<longrightarrow> ((member y l) = (member y (delete x l))))"
  apply (induct l)
   apply auto
  done

(* 1.3 : Intersection *)
fun intersection :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
  "intersection [] _ = []"
| "intersection (t#q) l = (if (member t l) then (t#(intersection q l)) else (intersection q l))"

lemma member_intersection: "((member x l1) \<and> (member x l2)) = (member x (intersection l1 l2))"
  apply (induct l1)
  apply (induct l2)
  apply simp
  apply simp
  apply auto
  done

lemma isSet_intersection: "(isSet l1) \<and> (isSet l2) \<longrightarrow> (isSet (intersection l1 l2))"
  apply (induct l1)
   apply (induct l2)
    apply simp
   apply simp
  using member_intersection by force

(* 1.4 : Union *)

fun union :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
  "union [] l = l"
| "union (t#q) l = (if (member t l) then (union q l) else (t#(union q l)))"

lemma member_union: "((member x l1) \<or> (member x l2)) = (member x (union l1 l2))"
  apply (induct l1)
   apply (induct l2)
    apply simp
   apply simp
  apply auto
  done

lemma isSet_union: "(isSet l1) \<and> (isSet l2) \<longrightarrow> (isSet (union l1 l2))"
  apply (induct l1)
   apply (induct l2)
    apply simp
   apply simp
  apply auto
  by (meson member_union)

(* 1.5 : Égalité *)

fun equal :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" where
  "equal [] l = (l = [])"
| "equal (t#q) l = ((member t l) \<and> (equal q (delete t l)))"

lemma "((isSet l1) \<and> (isSet l2)) \<longrightarrow> ((equal l1 l2) = (\<forall>x. (member x l1) = (member x l2)))"
  apply (induct l1 arbitrary: l2)
   apply (metis equal.simps(1) isSet.elims(2) tp2.member.simps(1) tp2.member.simps(2))
  apply simp
  apply (case_tac "member a l2")
   prefer 2
   apply auto[1]
  apply simp

  sorry

(* I could not prove this one so I made another one here below *)

fun cotains :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" where
  "contains l [] = True"
| "contains l (t#q) = ((member t l) \<and> (contains l q))"

fun equal2 :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" where
  "equal2 l1 l2 = ((contains l1 l2) \<and> (contains l2 l1))"

lemma contains_member: "(contains l1 l2) = (\<forall>x. ((member x l2) \<longrightarrow> (member x l1)))"
  apply (induct l2)
  apply auto
  done

lemma "((isSet l1) \<and> (isSet l2)) \<longrightarrow> ((equal2 l1 l2) = (\<forall>x. (member x l1) = (member x l2)))"
  using contains_member by auto

end


section \<open>Exponentiation of ordinals\<close>

theory Ordinal_Exp
  imports Kirby

begin

text \<open>Source: Schlöder, Julian.  Ordinal Arithmetic; available online at
    \url{http://www.math.uni-bonn.de/ag/logik/teaching/2012WS/Set%20theory/oa.pdf}\<close>

definition oexp :: "[V,V] \<Rightarrow> V" (infixr "\<up>" 80)
  where "oexp a b \<equiv> transrec (\<lambda>f x. if x=0 then 1
                                    else if Limit x then if a=0 then 0 else SUP \<xi> \<in> elts x. f \<xi>
                                    else f (\<Squnion>(elts x)) * a) b"

text \<open>@{term "0\<up>\<omega> = 1"} if we don't make a special case for Limit ordinals and zero\<close>

lemma oexp_0_right [simp]: "\<alpha>\<up>0 = 1"
  by (simp add: def_transrec [OF oexp_def])

lemma oexp_succ [simp]: "Ord \<beta> \<Longrightarrow> \<alpha>\<up>(succ \<beta>) = \<alpha>\<up>\<beta> * \<alpha>"
  by (simp add: def_transrec [OF oexp_def])

lemma oexp_Limit: "Limit \<beta> \<Longrightarrow> \<alpha>\<up>\<beta> = (if \<alpha>=0 then 0 else SUP \<xi> \<in> elts \<beta>. \<alpha>\<up>\<xi>)"
  by (auto simp: def_transrec [OF oexp_def, of _ \<beta>])

lemma oexp_1_right [simp]: "\<alpha>\<up>1 = \<alpha>"
  using one_V_def oexp_succ by fastforce

lemma oexp_1 [simp]: "Ord \<alpha> \<Longrightarrow> 1\<up>\<alpha> = 1"
  by (induction rule: Ord_induct3) (use Limit_def oexp_Limit in auto)

lemma oexp_0 [simp]: "Ord \<alpha> \<Longrightarrow> 0\<up>\<alpha> = (if \<alpha> = 0 then 1 else 0)"
  by (induction rule: Ord_induct3) (use Limit_def oexp_Limit in auto)

lemma oexp_eq_0_iff [simp]:
  assumes "Ord \<beta>" shows "\<alpha>\<up>\<beta> = 0 \<longleftrightarrow> \<alpha>=0 \<and> \<beta>\<noteq>0"
  using \<open>Ord \<beta>\<close>
proof (induction rule: Ord_induct3)
  case (Limit \<mu>)
  then show ?case
    using Limit_def oexp_Limit by auto
qed auto

lemma oexp_gt_0_iff [simp]:
  assumes "Ord \<beta>" shows "\<alpha>\<up>\<beta> > 0 \<longleftrightarrow> \<alpha>>0 \<or> \<beta>=0"
  by (simp add: assms less_V_def)

lemma ord_of_nat_oexp: "ord_of_nat (m^n) = ord_of_nat m\<up>ord_of_nat n"
proof (induction n)
  case (Suc n)
  then show ?case
    by (simp add: mult.commute [of m]) (simp add: ord_of_nat_mult)
qed auto

lemma omega_closed_oexp [intro]:
  assumes "\<alpha> \<in> elts \<omega>" "\<beta> \<in> elts \<omega>" shows "\<alpha>\<up>\<beta> \<in> elts \<omega>"
proof -
  obtain m n where "\<alpha> = ord_of_nat m" "\<beta> = ord_of_nat n"
    using assms elts_\<omega> by auto
  then have "\<alpha>\<up>\<beta> = ord_of_nat (m^n)"
    by (simp add: ord_of_nat_oexp)
  then show ?thesis
    by (simp add: \<omega>_def)
qed

lemma Ord_oexp [simp]:
  assumes "Ord \<alpha>" "Ord \<beta>" shows "Ord (\<alpha>\<up>\<beta>)"
  using \<open>Ord \<beta>\<close>
proof (induction rule: Ord_induct3)
  case (Limit \<alpha>)
  then show ?case
    by (auto simp: oexp_Limit image_iff intro: Ord_Sup)
qed (auto intro: Ord_mult assms)

text \<open>Lemma 3.19\<close>
lemma le_oexp:
  assumes "Ord \<alpha>" "Ord \<beta>" "\<beta> \<noteq> 0" shows "\<alpha> \<le> \<alpha>\<up>\<beta>"
  using \<open>Ord \<beta>\<close> \<open>\<beta> \<noteq> 0\<close>
proof (induction rule: Ord_induct3)
  case (succ \<beta>)
  then show ?case
    by simp (metis \<open>Ord \<alpha>\<close> le_0 le_mult mult.left_neutral oexp_0_right order_refl order_trans)
next
  case (Limit \<mu>)
  then show ?case
    by (metis Limit_def Limit_eq_Sup_self ZFC_in_HOL.Sup_upper eq_iff image_eqI image_ident oexp_1_right oexp_Limit replacement small_elts one_V_def)
qed auto

text \<open>Lemma 3.20\<close>
lemma le_oexp':
  assumes "Ord \<alpha>" "1 < \<alpha>" "Ord \<beta>" shows "\<beta> \<le> \<alpha>\<up>\<beta>"
proof (cases "\<beta> = 0")
  case True
  then show ?thesis
    by auto
next
  case False
  show ?thesis
    using \<open>Ord \<beta>\<close>
  proof (induction rule: Ord_induct3)
    case 0
    then show ?case
      by auto
  next
    case (succ \<gamma>)
    then have "\<alpha>\<up>\<gamma> * 1 < \<alpha>\<up>\<gamma> * \<alpha>"
      using \<open>Ord \<alpha>\<close> \<open>1 < \<alpha>\<close>
      by (metis le_mult less_V_def mult.right_neutral mult_cancellation not_less_0 oexp_eq_0_iff succ.hyps)
    then have " \<gamma> < \<alpha>\<up>succ \<gamma>"
      using succ.IH succ.hyps by auto
    then show ?case
      using False \<open>Ord \<alpha>\<close> \<open>1 < \<alpha>\<close> succ
      by (metis Ord_mem_iff_lt Ord_oexp Ord_succ elts_succ insert_subset less_eq_V_def less_imp_le)
  next
    case (Limit \<mu>)
    with False \<open>1 < \<alpha>\<close> show ?case
      by (force simp: Limit_def oexp_Limit intro: elts_succ)
  qed
qed

lemma oexp_Limit_le:
  assumes "\<beta> < \<gamma>" "Limit \<gamma>" "Ord \<beta>" "\<alpha> > 0" shows "\<alpha>\<up>\<beta> \<le> \<alpha>\<up>\<gamma>"
proof -
  have "Ord \<gamma>"
    using Limit_def assms(2) by blast
  with assms show ?thesis
    using Ord_mem_iff_lt ZFC_in_HOL.Sup_upper oexp_Limit by auto
qed

proposition oexp_less:
  assumes \<beta>: "\<beta> \<in> elts \<gamma>" and "Ord \<gamma>" and \<alpha>: "\<alpha> > 1" "Ord \<alpha>" shows "\<alpha>\<up>\<beta> < \<alpha>\<up>\<gamma>"
proof -
  obtain "\<beta> < \<gamma>" "Ord \<beta>"
    using Ord_in_Ord OrdmemD assms by auto
  have gt0: "\<alpha>\<up>\<beta> > 0"
    using \<open>Ord \<beta>\<close> \<alpha> dual_order.order_iff_strict by auto
  show ?thesis
    using \<open>Ord \<gamma>\<close> \<beta>
  proof (induction rule: Ord_induct3)
    case 0
    then show ?case
      by auto
  next
    case (succ \<delta>)
    then consider "\<beta> = \<delta>" | "\<beta> < \<delta>"
      using OrdmemD elts_succ by blast
    then show ?case
    proof cases
      case 1
      then have "(\<alpha>\<up>\<beta>) * 1 < (\<alpha>\<up>\<delta>) * \<alpha>"
        using Ord_1 Ord_oexp \<alpha> gt0 mult_cancel_less_iff succ.hyps by metis
      then show ?thesis
        by (simp add: succ.hyps)
    next
      case 2
      then have "(\<alpha>\<up>\<delta>) * 1 < (\<alpha>\<up>\<delta>) * \<alpha>"
        by (meson Ord_1 Ord_mem_iff_lt Ord_oexp \<open>Ord \<beta>\<close> \<alpha> gt0 less_trans mult_cancel_less_iff succ)
      with 2 show ?thesis
        using Ord_mem_iff_lt \<open>Ord \<beta>\<close> succ by auto
    qed
  next
    case (Limit \<gamma>)
    then obtain "Ord \<gamma>" "succ \<beta> < \<gamma>"
      using Limit_def Ord_in_Ord OrdmemD assms by auto
    have "\<alpha>\<up>\<beta> = (\<alpha>\<up>\<beta>) * 1"
      by simp
    also have "\<dots> < (\<alpha>\<up>\<beta>) * \<alpha>"
      using Ord_oexp \<open>Ord \<beta>\<close> assms gt0 mult_cancel_less_iff by blast
    also have "\<dots> = \<alpha>\<up>succ \<beta>"
      by (simp add: \<open>Ord \<beta>\<close>)
    also have "\<dots> \<le> (SUP \<xi> \<in> elts \<gamma>. \<alpha>\<up>\<xi>)"
    proof -
      have "succ \<beta> \<in> elts \<gamma>"
        using Limit.hyps Limit.prems Limit_def by auto
      then show ?thesis
        by (simp add: ZFC_in_HOL.Sup_upper)
    qed
    finally
    have "\<alpha>\<up>\<beta> < (SUP \<xi> \<in> elts \<gamma>. \<alpha>\<up>\<xi>)" .
    then show ?case
      using Limit.hyps oexp_Limit \<open>\<alpha> > 1\<close> by auto
  qed
qed

corollary oexp_less_iff:
  assumes "\<alpha> > 0" "Ord \<alpha>" "Ord \<beta>" "Ord \<gamma>" shows "\<alpha>\<up>\<beta> < \<alpha>\<up>\<gamma> \<longleftrightarrow> \<beta> \<in> elts \<gamma> \<and> \<alpha> > 1"
proof safe
  show "\<beta> \<in> elts \<gamma>" "1 < \<alpha>"
    if "\<alpha>\<up>\<beta> < \<alpha>\<up>\<gamma>"
  proof -
    show "\<alpha> > 1"
    proof (rule ccontr)
      assume "\<not> \<alpha> > 1"
      then consider "\<alpha>=0" | "\<alpha>=1"
        using \<open>Ord \<alpha>\<close> less_V_def mem_0_Ord by fastforce
      then show False
        by cases (use that \<open>\<alpha> > 0\<close> \<open>Ord \<beta>\<close> \<open>Ord \<gamma>\<close> in \<open>auto split: if_split_asm\<close>)
    qed
    show \<beta>: "\<beta> \<in> elts \<gamma>"
    proof (rule ccontr)
      assume "\<beta> \<notin> elts \<gamma>"
      then have "\<gamma> \<le> \<beta>"
        by (meson Ord_linear_le Ord_mem_iff_lt assms less_le_not_le)
      then consider "\<gamma> = \<beta>" | "\<gamma> < \<beta>"
        using less_V_def by blast
      then show False
      proof cases
        case 1
        then show ?thesis
          using that by blast
      next
        case 2
        with \<open>\<alpha> > 1\<close> have "\<alpha>\<up>\<gamma> < \<alpha>\<up>\<beta>"
          by (simp add: Ord_mem_iff_lt assms oexp_less)
        with that show ?thesis
          by auto
      qed
    qed
  qed
  show "\<alpha>\<up>\<beta> < \<alpha>\<up>\<gamma>" if "\<beta> \<in> elts \<gamma>" "1 < \<alpha>"
    using that by (simp add: assms oexp_less)
qed

lemma \<omega>_oexp_iff [simp]: "\<lbrakk>Ord \<alpha>; Ord \<beta>\<rbrakk> \<Longrightarrow> \<omega>\<up>\<alpha> = \<omega>\<up>\<beta> \<longleftrightarrow> \<alpha>=\<beta>"
  by (metis Ord_\<omega> Ord_linear \<omega>_gt1 less_irrefl oexp_less)

lemma Limit_oexp:
  assumes "Limit \<gamma>" "Ord \<alpha>" "\<alpha> > 1" shows "Limit (\<alpha>\<up>\<gamma>)"
  unfolding Limit_def
proof safe
  show O\<alpha>\<gamma>: "Ord (\<alpha>\<up>\<gamma>)"
    using Limit_def Ord_oexp \<open>Limit \<gamma>\<close> assms(2) by blast
  show 0: "0 \<in> elts (\<alpha>\<up>\<gamma>)"
    using Limit_def oexp_Limit \<open>Limit \<gamma>\<close> \<open>\<alpha> > 1\<close> by fastforce
  have "Ord \<gamma>"
    using Limit_def \<open>Limit \<gamma>\<close> by blast
  fix x
  assume x: "x \<in> elts (\<alpha>\<up>\<gamma>)"
  with \<open>Limit \<gamma>\<close> \<open>\<alpha> > 1\<close>
  obtain \<beta> where "\<beta> < \<gamma>" "Ord \<beta>" "Ord x" and x\<beta>: "x \<in> elts (\<alpha>\<up>\<beta>)"
    apply (simp add: oexp_Limit split: if_split_asm)
    using Ord_in_Ord OrdmemD \<open>Ord \<gamma>\<close> O\<alpha>\<gamma> x by blast
  then have O\<alpha>\<beta>: "Ord (\<alpha>\<up>\<beta>)"
    using Ord_oexp assms(2) by blast
  have "\<beta> \<in> elts \<gamma>"
    by (simp add: Ord_mem_iff_lt \<open>Ord \<beta>\<close> \<open>Ord \<gamma>\<close> \<open>\<beta> < \<gamma>\<close>)
  moreover have "\<alpha> \<noteq> 0"
    using \<open>\<alpha> > 1\<close> by blast
  ultimately have \<alpha>\<beta>\<gamma>: "\<alpha>\<up>\<beta> \<le> \<alpha>\<up>\<gamma>"
    by (simp add: Sup_upper oexp_Limit \<open>Limit \<gamma>\<close>)
  have "succ x \<le> \<alpha>\<up>\<beta>"
    by (simp add: OrdmemD O\<alpha>\<beta> \<open>Ord x\<close> succ_le_iff x\<beta>)
  then consider "succ x < \<alpha>\<up>\<beta>" | "succ x = \<alpha>\<up>\<beta>"
    using le_neq_trans by blast
  then show "succ x \<in> elts (\<alpha>\<up>\<gamma>)"
  proof cases
    case 1
    with \<alpha>\<beta>\<gamma> show ?thesis
      using O\<alpha>\<beta> Ord_mem_iff_lt \<open>Ord x\<close> by blast
  next
    case 2
    then have "succ \<beta> < \<gamma>"
      using Limit_def OrdmemD \<open>\<beta> \<in> elts \<gamma>\<close> assms(1) by auto
    have ge1: "1 \<le> \<alpha>\<up>\<beta>"
      by (metis "2" Ord_0 \<open>Ord x\<close> le_0 le_succ_iff one_V_def)
    have "succ x < succ (\<alpha>\<up>\<beta>)"
      using "2" O\<alpha>\<beta> succ_le_iff by auto
    also have "\<dots> \<le> (\<alpha>\<up>\<beta>) + (\<alpha>\<up>\<beta>)"
      using ge1 by (simp add: succ_eq_add1)
    also have "\<dots> = (\<alpha>\<up>\<beta>) * succ (succ 0)"
      by (simp add: mult_succ)
    also have "\<dots> \<le> (\<alpha>\<up>\<beta>) * \<alpha>"
      using O\<alpha>\<beta> Ord_succ assms(2) assms(3) one_V_def succ_le_iff by auto
    also have "\<dots> = \<alpha>\<up>succ \<beta>"
      by (simp add: \<open>Ord \<beta>\<close>)
    also have "\<dots> \<le> \<alpha>\<up>\<gamma>"
      by (meson Limit_def \<open>\<beta> \<in> elts \<gamma>\<close> assms dual_order.order_iff_strict oexp_less)
  finally show ?thesis
    by (simp add: "2" O\<alpha>\<beta> O\<alpha>\<gamma> Ord_mem_iff_lt)
  qed
qed

lemma oexp_mono:
  assumes \<alpha>: "Ord \<alpha>" "\<alpha> \<noteq> 0" and \<beta>: "Ord \<beta>" "\<gamma> \<sqsubseteq> \<beta>" shows "\<alpha>\<up>\<gamma> \<le> \<alpha>\<up>\<beta>"
  using \<beta>
proof (induction rule: Ord_induct3)
  case 0
  then show ?case
    by simp
next
  case (succ \<beta>)
  with \<alpha> le_mult show ?case
    by (auto simp: le_TC_succ)
next
  case (Limit \<mu>)
  then have "\<alpha>\<up>\<gamma> \<le> \<Squnion> ((\<up>) \<alpha> ` elts \<mu>)"
    using Limit.hyps Ord_less_TC_mem \<open>\<alpha> \<noteq> 0\<close> le_TC_def by (auto simp: oexp_Limit Limit_def)
  then show ?case
    using \<alpha> by (simp add: oexp_Limit Limit.hyps)
qed

lemma oexp_mono_le:
  assumes "\<gamma> \<le> \<beta>" "\<alpha> \<noteq> 0" "Ord \<alpha>" "Ord \<beta>" "Ord \<gamma>" shows "\<alpha>\<up>\<gamma> \<le> \<alpha>\<up>\<beta>"
  by (simp add: assms oexp_mono vle2 vle_iff_le_Ord)

lemma oexp_sup:
  assumes "\<alpha> \<noteq> 0" "Ord \<alpha>" "Ord \<beta>" "Ord \<gamma>" shows "\<alpha>\<up>(\<beta> \<squnion> \<gamma>) = \<alpha>\<up>\<beta> \<squnion> \<alpha>\<up>\<gamma>"
  by (metis Ord_linear_le assms oexp_mono_le sup.absorb2 sup.orderE)

lemma oexp_Sup:
  assumes \<alpha>: "\<alpha> \<noteq> 0" "Ord \<alpha>" and X: "X \<subseteq> ON" "small X" "X \<noteq> {}" shows "\<alpha>\<up>\<Squnion> X = \<Squnion> ((\<up>) \<alpha> ` X)"
proof (rule order_antisym)
  show "\<Squnion> ((\<up>) \<alpha> ` X) \<le> \<alpha>\<up>\<Squnion> X"
    by (metis ON_imp_Ord Ord_Sup ZFC_in_HOL.Sup_upper assms cSUP_least oexp_mono_le)
next
  have "Ord (Sup X)"
    using Ord_Sup X by auto
  then show "\<alpha>\<up>\<Squnion> X \<le> \<Squnion> ((\<up>) \<alpha> ` X)"
  proof (cases rule: Ord_cases)
    case 0
    then show ?thesis
      using X dual_order.antisym by fastforce
  next
    case (succ \<beta>)
    then show ?thesis
      using ZFC_in_HOL.Sup_upper X succ_in_Sup_Ord by auto
  next
    case limit
    show ?thesis
    proof (clarsimp simp: assms oexp_Limit limit)
      fix x y z
      assume x: "x \<in> elts (\<alpha> \<up> y)" and "z \<in> X" "y \<in> elts z"
      then have "\<alpha> \<up> y \<le> \<alpha> \<up> z"
        by (meson ON_imp_Ord Ord_in_Ord OrdmemD \<alpha> \<open>X \<subseteq> ON\<close> le_less oexp_mono_le)
      with x have "x \<in> elts (\<alpha> \<up> z)" by blast
      then show "\<exists>u\<in>X. x \<in> elts (\<alpha> \<up> u)"
        using \<open>z \<in> X\<close> by blast
    qed
  qed
qed

lemma omega_le_Limit:
  assumes "Limit \<mu>" shows "\<omega> \<le> \<mu>"
proof
  fix \<rho>
  assume "\<rho> \<in> elts \<omega>"
  then obtain n where "\<rho> = ord_of_nat n"
    using elts_\<omega> by auto
  have "ord_of_nat n \<in> elts \<mu>"
    by (induction n) (use Limit_def assms in auto)
  then show "\<rho> \<in> elts \<mu>"
    using \<open>\<rho> = ord_of_nat n\<close> by auto
qed

lemma finite_omega_power [simp]:
  assumes "1 < n" "n \<in> elts \<omega>" shows "n\<up>\<omega> = \<omega>"
proof (rule order_antisym)
  have "\<Squnion> ((\<up>) (ord_of_nat k) ` elts \<omega>) \<le> \<omega>" for k
  proof (induction k)
    case 0
    then show ?case
      by auto
  next
    case (Suc k)
    then show ?case
      by (metis Ord_\<omega> OrdmemD Sup_eq_0_iff ZFC_in_HOL.SUP_le_iff le_0 le_less omega_closed_oexp ord_of_nat_\<omega>)
  qed
  then show "n\<up>\<omega> \<le> \<omega>"
    using assms
    by (simp add: elts_\<omega> oexp_Limit) metis
  show "\<omega> \<le> n\<up>\<omega>"
    using Ord_in_Ord assms le_oexp' by blast
qed

proposition oexp_add:
  assumes "Ord \<alpha>" "Ord \<beta>" "Ord \<gamma>" shows "\<alpha>\<up>(\<beta> + \<gamma>) = \<alpha>\<up>\<beta> * \<alpha>\<up>\<gamma>"
proof (cases \<open>\<alpha> = 0\<close>)
  case True
  then show ?thesis
    using assms by simp
next
  case False
  show ?thesis
    using \<open>Ord \<gamma>\<close>
  proof (induction rule: Ord_induct3)
    case 0
    then show ?case
      by auto
  next
    case (succ \<xi>)
    then show ?case
      using \<open>Ord \<beta>\<close> by (auto simp: plus_V_succ_right mult.assoc)
  next
    case (Limit \<mu>)
    have "\<alpha>\<up>(\<beta> + (SUP \<xi>\<in>elts \<mu>. \<xi>)) = (SUP \<xi>\<in>elts (\<beta> + \<mu>). \<alpha>\<up>\<xi>)"
      by (simp add: Limit.hyps oexp_Limit assms False)
    also have "\<dots> = (SUP \<xi> \<in> {\<xi>. Ord \<xi> \<and> \<beta> + \<xi> < \<beta> + \<mu>}. \<alpha>\<up>(\<beta> + \<xi>))"
    proof (rule Sup_eq_Sup)
      show "(\<lambda>\<xi>. \<alpha>\<up>(\<beta> + \<xi>)) ` {\<xi>. Ord \<xi> \<and> \<beta> + \<xi> < \<beta> + \<mu>} \<subseteq> (\<up>) \<alpha> ` elts (\<beta> + \<mu>)"
        using Limit.hyps Limit_def Ord_mem_iff_lt imageI by blast
      fix x
      assume "x \<in> (\<up>) \<alpha> ` elts (\<beta> + \<mu>)"
      then obtain \<xi> where \<xi>: "\<xi> \<in> elts (\<beta> + \<mu>)" and x: "x = \<alpha>\<up>\<xi>"
        by auto
      have "\<exists>\<gamma>. Ord \<gamma> \<and> \<gamma> < \<mu> \<and> \<alpha>\<up>\<xi> \<le> \<alpha>\<up>(\<beta> + \<gamma>)"
      proof (rule mem_plus_V_E [OF \<xi>])
        assume "\<xi> \<in> elts \<beta>"
        then have "\<alpha>\<up>\<xi> \<le> \<alpha>\<up>\<beta>"
          by (meson arg_subset_TC assms False le_TC_def less_TC_def oexp_mono vsubsetD)
        with zero_less_Limit [OF \<open>Limit \<mu>\<close>]
        show "\<exists>\<gamma>. Ord \<gamma> \<and> \<gamma> < \<mu> \<and> \<alpha>\<up>\<xi> \<le> \<alpha>\<up>(\<beta> + \<gamma>)"
          by force
      next
        fix \<delta>
        assume "\<delta> \<in> elts \<mu>" and "\<xi> = \<beta> + \<delta>"
        have "Ord \<delta>"
          using Limit.hyps Limit_def Ord_in_Ord \<open>\<delta> \<in> elts \<mu>\<close> by blast
        moreover have "\<delta> < \<mu>"
          using Limit.hyps Limit_def OrdmemD \<open>\<delta> \<in> elts \<mu>\<close> by auto
        ultimately show "\<exists>\<gamma>. Ord \<gamma> \<and> \<gamma> < \<mu> \<and> \<alpha>\<up>\<xi> \<le> \<alpha>\<up>(\<beta> + \<gamma>)"
          using \<open>\<xi> = \<beta> + \<delta>\<close> by blast
      qed
      then show "\<exists>y\<in>(\<lambda>\<xi>. \<alpha>\<up>(\<beta> + \<xi>)) ` {\<xi>. Ord \<xi> \<and> \<beta> + \<xi> < \<beta> + \<mu>}. x \<le> y"
        using x by auto
    qed auto
    also have "\<dots> = (SUP \<xi>\<in>elts \<mu>. \<alpha>\<up>(\<beta> + \<xi>))"
      using \<open>Limit \<mu>\<close>
      by (simp add: Ord_Collect_lt Limit_def)
    also have "\<dots> = (SUP \<xi>\<in>elts \<mu>. \<alpha>\<up>\<beta> * \<alpha>\<up>\<xi>)"
      using Limit.IH by auto
    also have "\<dots> = \<alpha>\<up>\<beta> * \<alpha>\<up>(SUP \<xi>\<in>elts \<mu>. \<xi>)"
      using \<open>\<alpha> \<noteq> 0\<close> Limit.hyps
      by (simp add: image_image oexp_Limit mult_Sup_distrib)
    finally show ?case .
  qed
qed

proposition oexp_mult:
  assumes "Ord \<alpha>" "Ord \<beta>" "Ord \<gamma>" shows "\<alpha>\<up>(\<beta> * \<gamma>) = (\<alpha>\<up>\<beta>)\<up>\<gamma>"
proof (cases "\<alpha> = 0 \<or> \<beta> = 0")
  case True
  then show ?thesis
    by (auto simp: \<open>Ord \<beta>\<close> \<open>Ord \<gamma>\<close>)
next
  case False
  show ?thesis
    using \<open>Ord \<gamma>\<close>
  proof (induction rule: Ord_induct3)
    case 0
    then show ?case
      by auto
  next
    case succ
    then show ?case
      using assms by (auto simp: mult_succ oexp_add)
  next
    case (Limit \<mu>)
    have Lim: "Limit (\<Squnion> ((*) \<beta> ` elts \<mu>))"
      unfolding Limit_def
    proof (intro conjI allI impI)
      show "Ord (\<Squnion> ((*) \<beta> ` elts \<mu>))"
        using Limit.hyps Limit_def Ord_in_Ord \<open>Ord \<beta>\<close> by (auto intro: Ord_Sup)
      have "succ 0 \<in> elts \<mu>"
        using Limit.hyps Limit_def by blast
      then show "0 \<in> elts (\<Squnion> ((*) \<beta> ` elts \<mu>))"
        using False \<open>Ord \<beta>\<close> mem_0_Ord by force
      show "succ y \<in> elts (\<Squnion> ((*) \<beta> ` elts \<mu>))"
        if "y \<in> elts (\<Squnion> ((*) \<beta> ` elts \<mu>))" for y
        using that False Limit.hyps
        apply (clarsimp simp: Limit_def)
        by (metis Ord_in_Ord Ord_linear Ord_mem_iff_lt Ord_mult Ord_succ assms(2) less_V_def mult_cancellation mult_succ not_add_mem_right succ_le_iff succ_ne_self)
    qed
    have "\<alpha>\<up>(\<beta> * (SUP \<xi>\<in>elts \<mu>. \<xi>)) = \<alpha>\<up>\<Squnion> ((*) \<beta> ` elts \<mu>)"
      by (simp add: mult_Sup_distrib)
    also have "\<dots> = \<Squnion> (\<Union>x\<in>elts \<mu>. (\<up>) \<alpha> ` elts (\<beta> * x))"
      using False Lim oexp_Limit by fastforce
    also have "\<dots> = (SUP x\<in>elts \<mu>. \<alpha>\<up>(\<beta> * x))"
    proof (rule Sup_eq_Sup)
      show "(\<lambda>x. \<alpha>\<up>(\<beta> * x)) ` elts \<mu> \<subseteq> (\<Union>x\<in>elts \<mu>. (\<up>) \<alpha> ` elts (\<beta> * x))"
        using \<open>Ord \<alpha>\<close> \<open>Ord \<beta>\<close> False Limit
        apply clarsimp
        by (metis Limit_def elts_succ imageI insertI1 mem_0_Ord mult_add_mem_0)
      show "\<exists>y\<in>(\<lambda>x. \<alpha>\<up>(\<beta> * x)) ` elts \<mu>. x \<le> y"
        if "x \<in> (\<Union>x\<in>elts \<mu>. (\<up>) \<alpha> ` elts (\<beta> * x))" for x
        using that \<open>Ord \<alpha>\<close> \<open>Ord \<beta>\<close> False Limit
        by clarsimp (metis Limit_def Ord_in_Ord Ord_mult VWO_TC_le mem_imp_VWO oexp_mono)
    qed auto
    also have "\<dots> = \<Squnion> ((\<up>) (\<alpha>\<up>\<beta>) ` elts (SUP \<xi>\<in>elts \<mu>. \<xi>))"
      using Limit.IH Limit.hyps by auto
    also have "\<dots> = (\<alpha>\<up>\<beta>)\<up>(SUP \<xi>\<in>elts \<mu>. \<xi>)"
      using False Limit.hyps oexp_Limit \<open>Ord \<beta>\<close> by auto
    finally show ?case .
  qed
qed

lemma Limit_omega_oexp:
  assumes "Ord \<delta>" "\<delta> \<noteq> 0"
  shows "Limit (\<omega>\<up>\<delta>)"
  using assms
proof (cases \<delta> rule: Ord_cases)
  case 0
  then show ?thesis
    using assms(2) by blast
next
  case (succ l)
  have *: "succ \<beta> \<in> elts (\<omega>\<up>l * n + \<omega>\<up>l)"
    if n: "n \<in> elts \<omega>" and \<beta>: "\<beta> \<in> elts (\<omega>\<up>l * n)" for n \<beta>
  proof -
    obtain "Ord n" "Ord \<beta>"
      by (meson Ord_\<omega> Ord_in_Ord Ord_mult Ord_oexp \<beta> n succ(1))
    obtain oo: "Ord (\<omega>\<up>l)" "Ord (\<omega>\<up>l * n)"
      by (simp add: \<open>Ord n\<close> succ(1))
    moreover have f4: "\<beta> < \<omega>\<up>l * n"
      using oo Ord_mem_iff_lt \<open>Ord \<beta>\<close> \<open>\<beta> \<in> elts (\<omega>\<up>l * n)\<close> by blast
    moreover have f5: "Ord (succ \<beta>)"
      using \<open>Ord \<beta>\<close> by blast
    moreover have "\<omega>\<up>l \<noteq> 0"
      using oexp_eq_0_iff omega_nonzero succ(1) by blast
    ultimately show ?thesis
      by (metis add_less_cancel_left Ord_\<omega> Ord_add Ord_mem_iff_lt OrdmemD \<open>Ord \<beta>\<close> add.right_neutral dual_order.strict_trans2 oexp_gt_0_iff succ(1) succ_le_iff zero_in_omega)
  qed
  show ?thesis
    using succ
    apply (clarsimp simp: Limit_def mem_0_Ord)
    apply (simp add: mult_Limit)
    by (metis * mult_succ succ_in_omega)
next
  case limit
  then show ?thesis
    by (metis Limit_oexp Ord_\<omega> OrdmemD one_V_def succ_in_omega zero_in_omega)
qed

lemma \<omega>_power_succ_gtr: "Ord \<alpha> \<Longrightarrow> \<omega> \<up> \<alpha> * ord_of_nat n < \<omega> \<up> succ \<alpha>"
  by (simp add: OrdmemD)

lemma countable_oexp:
  assumes \<nu>: "\<alpha> \<in> elts \<omega>1"
  shows "\<omega> \<up> \<alpha> \<in> elts \<omega>1"
proof -
  have "Ord \<alpha>"
    using Ord_\<omega>1 Ord_in_Ord assms by blast
  then show ?thesis
    using assms
  proof (induction rule: Ord_induct3)
    case 0
    then show ?case
      by (simp add: Ord_mem_iff_lt)
  next
    case (succ \<alpha>)
    then have "countable (elts (\<omega> \<up> \<alpha> * \<omega>))"
      by (simp add: succ_in_Limit_iff countable_mult less_\<omega>1_imp_countable)
    then show ?case
      using Ord_mem_iff_lt countable_iff_less_\<omega>1 succ.hyps by auto
  next
    case (Limit \<alpha>)
    with Ord_\<omega>1 have "countable (\<Union>\<beta>\<in>elts \<alpha>. elts (\<omega> \<up> \<beta>))" "Ord (\<omega> \<up> \<Squnion> (elts \<alpha>))"
      by (force simp: Limit_def intro: Ord_trans less_\<omega>1_imp_countable)+
    then have "\<omega> \<up> \<Squnion> (elts \<alpha>) < \<omega>1"
      using Limit.hyps countable_iff_less_\<omega>1 oexp_Limit by fastforce
    then show ?case
      using Limit.hyps Limit_def Ord_mem_iff_lt by auto
  qed
qed

end


(*by Ammer*)
theory VEBT_Pred imports VEBT_MinMax VEBT_Insert
begin

section \<open>The Predecessor Operation\<close>

definition is_pred_in_set :: "nat set \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where
  "is_pred_in_set xs x y =  (y \<in> xs \<and> y < x \<and> (\<forall> z \<in> xs. (z < x \<longrightarrow> z \<le> y)))"

context VEBT_internal begin

subsection \<open>Lemmas on Sets and Predecessorship\<close>

corollary pred_member: "is_pred_in_set (set_vebt' t) x y = (vebt_member t y \<and> y < x \<and> (\<forall> z. vebt_member t z \<and> z < x \<longrightarrow> z \<le> y))"
  using is_pred_in_set_def set_vebt'_def by auto

lemma "finite (A:: nat set) \<Longrightarrow> A \<noteq> {}\<Longrightarrow> Max A \<in> A"
proof(induction A rule: finite.induct)
  case emptyI
  then show ?case by blast
next
  case (insertI A a)
  then show ?case
    by (meson Max_in finite_insert)
qed

lemma obtain_set_pred: assumes "(x::nat) > z " and "min_in_set A z" and "finite A"  shows "\<exists> y. is_pred_in_set A x y"
proof-
  have "{y \<in> A. y < x} \<noteq> {}"
    using assms(1) assms(2) min_in_set_def by auto
  hence "Max {y \<in> A. y < x} \<in> {y \<in> A. y < x}"
    by (metis (full_types) Max_eq_iff finite_M_bounded_by_nat)
  moreover have "i \<in> A\<Longrightarrow> i < x \<Longrightarrow> i \<le> Max {y \<in> A. y < x} " for i by simp
  ultimately have "is_pred_in_set A x (Max {y \<in> A. y < x})"
    using is_pred_in_set_def by auto
  then show?thesis by auto
qed

lemma pred_none_empty: assumes "(\<nexists> x. is_pred_in_set (xs) a x)"  and "finite xs"shows "\<not> (\<exists> x \<in> xs. ord_class.less x a)"
proof-
  have "\<exists> x \<in> xs. ord_class.less x a \<Longrightarrow> False"
  proof-
    assume "\<exists> x \<in> xs. ord_class.less x a"
    hence "{x \<in> xs. ord_class.less x  a} \<noteq> {}" by auto
    hence "Max {y \<in> xs. y < a} \<in> {y \<in> xs. y < a}"
      by (metis (full_types) Max_eq_iff finite_M_bounded_by_nat)
    moreover hence "i \<in> xs \<Longrightarrow>  ord_class.less i  a\<Longrightarrow>
             ord_class.less_eq i (Max {y \<in> xs. ord_class.less y  a}) " for i
      by (simp add: assms(2))
    ultimately have "is_pred_in_set xs a (Max {y \<in> xs. y < a})"
      using is_pred_in_set_def by auto
    then show False
      using assms(1) by blast
  qed
  then show ?thesis by blast
qed

end

subsection \<open>The actual Function for Predecessor Search\<close>

context begin
  interpretation VEBT_internal .

fun vebt_pred :: "VEBT \<Rightarrow> nat \<Rightarrow> nat option" where
  "vebt_pred (Leaf _ _) 0 = None"|
  "vebt_pred (Leaf a _) (Suc 0) = (if a then Some 0 else None)"|
  "vebt_pred (Leaf a b) _ = (if b then Some 1 else if a then Some 0 else None)"|
  "vebt_pred (Node None _ _ _) _ = None"|
  "vebt_pred (Node _ 0 _ _) _ = None"|
  "vebt_pred (Node _ (Suc 0) _ _) _ = None"|
  "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = (
         if x > ma then Some ma
         else (let l = low x (deg div 2); h = high x (deg div 2) in
               if h < length treeList then
                  let minlow = vebt_mint (treeList ! h) in (
                      if minlow \<noteq> None \<and> (Some l >\<^sub>o  minlow) then
                         Some (2^(deg div 2)) *\<^sub>o Some h +\<^sub>o vebt_pred (treeList ! h) l
                      else let pr = vebt_pred summary h in
                               if pr = None then (
                                  if x > mi then Some mi
                                  else None)
                               else Some (2^(deg div 2)) *\<^sub>o pr +\<^sub>o vebt_maxt (treeList ! the pr) )
               else None))"

end

context VEBT_internal begin
subsection \<open>Auxiliary Lemmas\<close>

lemma pred_max:
  assumes "deg \<ge> 2" and "(x::nat) > ma"
  shows "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some ma"
  by (metis VEBT_Pred.vebt_pred.simps(7) add_2_eq_Suc assms(1) assms(2) le_add_diff_inverse)

lemma pred_lesseq_max:
  assumes "deg \<ge> 2" and "(x::nat) \<le> ma"
  shows "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =  (let l = low x (deg div 2); h = high x (deg div 2) in
                       if h < length treeList then

                            let minlow = vebt_mint (treeList ! h) in
                            (if minlow \<noteq> None \<and> (Some l >\<^sub>o  minlow) then
                                                    Some (2^(deg div 2)) *\<^sub>o Some h +\<^sub>o vebt_pred (treeList ! h) l
                             else let pr = vebt_pred summary h in
                             if pr = None then (if x > mi then Some mi else None)
                             else Some (2^(deg div 2)) *\<^sub>o pr +\<^sub>o vebt_maxt (treeList ! the pr) )

                     else None)"
  by (smt VEBT_Pred.vebt_pred.simps(7) add_numeral_left assms(1) assms(2) leD le_add_diff_inverse numerals(1) plus_1_eq_Suc semiring_norm(2))

lemma pred_list_to_short:
  assumes "deg \<ge> 2" and "ord_class.less_eq x ma" and " high x (deg div 2) \<ge> length treeList"
  shows "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = None"
  by (simp add: assms(1) assms(2) assms(3) leD pred_lesseq_max)

lemma pred_less_length_list:
  assumes "deg \<ge> 2" and "ord_class.less_eq x  ma" and " high x (deg div 2) < length treeList"
  shows
  "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = (let l = low x (deg div 2); h = high x (deg div 2); minlow = vebt_mint (treeList ! h) in
                            (if minlow \<noteq> None \<and> (Some l >\<^sub>o  minlow) then
                                                    Some (2^(deg div 2)) *\<^sub>o Some h +\<^sub>o vebt_pred (treeList ! h) l
                             else let pr = vebt_pred summary h in
                             if pr = None then (if x > mi then Some mi else None)
                             else Some (2^(deg div 2)) *\<^sub>o pr +\<^sub>o vebt_maxt (treeList ! the pr) ))"
  by (simp add: assms(1) assms(2) assms(3) pred_lesseq_max)

subsection \<open>Correctness Proof\<close>

theorem pred_corr: "invar_vebt t n \<Longrightarrow> vebt_pred t x = Some px == is_pred_in_set (set_vebt' t) x px"
proof(induction t n arbitrary: x px rule: invar_vebt.induct)
  case (1 a b)
  then show ?case
  proof(cases x)
    case 0
    then show ?thesis
      by (simp add: is_pred_in_set_def)
  next
    case (Suc sucX)
    hence "x \<ge> 0 \<and> x = Suc sucX" by auto
    then show ?thesis
    proof(cases sucX)
      case 0
      then show ?thesis
        by (simp add: Suc pred_member)
    next
      case (Suc nat)
      hence "x\<ge> 2"
        by (simp add: \<open>0 \<le> x \<and> x = Suc sucX\<close>)
      then show ?thesis
      proof(cases b)
        case True
        hence "vebt_pred (Leaf a b) x = Some 1"
          by (simp add: Suc \<open>0 \<le> x \<and> x = Suc sucX\<close>)
        moreover have "is_pred_in_set (set_vebt' (Leaf a b)) x 1"
          by (simp add: Suc True \<open>0 \<le> x \<and> x = Suc sucX\<close> pred_member)
        ultimately show ?thesis
          using pred_member by auto
      next
        case False
        hence "b = False" by simp
        then show ?thesis
        proof(cases a)
          case True
          hence "vebt_pred (Leaf a b) x = Some 0"
            by (simp add: False Suc \<open>0 \<le> x \<and> x = Suc sucX\<close>)
          moreover have "is_pred_in_set (set_vebt' (Leaf a b)) x 0"
            by (simp add: False True \<open>0 \<le> x \<and> x = Suc sucX\<close> pred_member)
          ultimately show ?thesis
            by (metis False VEBT_Member.vebt_member.simps(1) option.sel pred_member)
        next
          case False
          then show ?thesis
            by (simp add: Suc \<open>0 \<le> x \<and> x = Suc sucX\<close> pred_member)
        qed
      qed
    qed
  qed
next
  case (2 treeList n summary m deg)
  then show ?case
    by (simp add: pred_member)
next
  case (3 treeList n summary m deg)
  then show ?case
    by (simp add: pred_member)
next
  case (4 treeList n summary m deg mi ma)
  hence "n = m" and "n \<ge> 1" and "deg \<ge> 2" and "deg = n + m"
       apply blast+
    using "4.hyps"(2) "4.hyps"(5) Suc_le_eq deg_not_0 apply auto[1]
    using "4.hyps"(2) "4.hyps"(5) "4.hyps"(6) deg_not_0 apply fastforce
    by (simp add: "4.hyps"(6))
  moreover hence thisvalid:"invar_vebt (Node (Some (mi, ma)) deg treeList summary) deg"
    using 4 invar_vebt.intros(4)[of treeList n summary m]  by blast
  ultimately have "deg div 2 =n" and "length treeList = 2^n"
    using add_self_div_2 apply blast by (simp add: "4.hyps"(4) "4.hyps"(5))
  then show ?case
  proof(cases "x > ma")
    case True
    hence 0: "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some ma"
      by (simp add: \<open>2 \<le> deg\<close> pred_max)
    have 1:"ma = the (vebt_maxt (Node (Some (mi, ma)) deg treeList summary))" by simp
    hence "ma \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary)"
      by (metis VEBT_Member.vebt_member.simps(5) \<open>2 \<le> deg\<close> add_numeral_left arith_simps(1) le_add_diff_inverse mem_Collect_eq numerals(1) plus_1_eq_Suc set_vebt'_def)
    hence 2:"y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary) \<Longrightarrow> y \<le> x" for y
      using "4.hyps"(9) True member_inv set_vebt'_def by fastforce
    hence 3: "y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary) \<Longrightarrow> (y < ma \<Longrightarrow> y \<le> x)" for y by blast
    hence 4: "\<forall> y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary). y < ma \<longrightarrow> y \<le> x" by blast
    hence "is_pred_in_set (set_vebt' (Node (Some (mi, ma)) deg treeList summary)) x ma"
      by (metis "4.hyps"(9) True \<open>ma \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary)\<close> less_or_eq_imp_le mem_Collect_eq member_inv pred_member set_vebt'_def)
    then show ?thesis
      by (metis "0" option.sel leD le_less_Suc_eq not_less_eq pred_member)
  next
    case False
    hence "x \<le> ma"by simp
    then show ?thesis
    proof(cases "high x (deg div 2)< length treeList ")
      case True
      hence "high x n < 2^n \<and> low x n < 2^n"
        by (simp add: \<open>deg div 2 = n\<close> \<open>length treeList = 2 ^ n\<close> low_def)
      let ?l = "low x (deg div 2)"
      let ?h = "high x (deg div 2)"
      let ?minlow = "vebt_mint (treeList ! ?h)"
      let ?pr = "vebt_pred summary ?h"
      have 1:"vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =
                           (if ?minlow \<noteq> None \<and> (Some ?l >\<^sub>o  ?minlow) then
                                                    Some (2^(deg div 2)) *\<^sub>o Some ?h +\<^sub>o vebt_pred (treeList ! ?h) ?l
                             else let pr = vebt_pred summary ?h in
                             if pr = None then (if x > mi then Some mi else None)
                             else Some (2^(deg div 2)) *\<^sub>o pr +\<^sub>o vebt_maxt (treeList ! the pr) )"
        by (smt True \<open>2 \<le> deg\<close> \<open>x \<le> ma\<close> pred_less_length_list)
      then show ?thesis
      proof(cases "?minlow \<noteq> None \<and> (Some ?l >\<^sub>o  ?minlow)")
        case True
        then obtain minl where 00:"(Some minl = ?minlow) \<and> ?l > minl" by auto
        have 01:"invar_vebt ((treeList ! ?h)) n \<and> (treeList ! ?h) \<in> set treeList "
          by (simp add: "4.hyps"(1) "4.hyps"(4) "4.hyps"(5) \<open>deg div 2 = n\<close> \<open>high x n < 2 ^ n \<and> low x n < 2 ^ n\<close>)
        have  02:"vebt_member ((treeList ! ?h)) minl"
          using "00" "01" mint_member by auto
        hence 03: "\<exists> y. y < ?l \<and> vebt_member ((treeList ! ?h)) y"
          using "00" by blast
        hence afinite: "finite (set_vebt' (treeList ! ?h)) "
          using "01" set_vebt_finite by blast
        then obtain predy where 04:"is_pred_in_set (set_vebt' (treeList ! ?h)) ?l predy"
          using "00" "01" mint_corr obtain_set_pred by fastforce
        hence 05:"Some predy =  vebt_pred (treeList ! ?h) ?l"  using 4(1) 01 by force
        hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x  =  Some (2^(deg div 2)*  ?h + predy) "
          using  "1" True add_def mul_def option_shift.simps(3) by metis
        hence 06: "predy \<in> set_vebt' (treeList ! ?h)"
          using "04" is_pred_in_set_def by blast
        hence 07: "predy < 2^(deg div 2) \<and> ?h < 2^(deg div 2) \<and> deg div 2 + deg div 2 = deg"
          using "01" "04" "4.hyps"(5) "4.hyps"(6) \<open>high x n < 2 ^ n \<and> low x n < 2 ^ n\<close> member_bound pred_member by auto
        let ?y = "2^(deg div 2)*  ?h + predy"
        have 08: "vebt_member (treeList ! ?h) predy"
          using "06" set_vebt'_def by auto
        hence 09: "both_member_options (treeList ! ?h) predy"
          using "01" both_member_options_equiv_member by blast
        have 10: "high ?y (deg div 2) = ?h \<and> low ?y (deg div 2) = predy"
          by (simp add: "07" high_inv low_inv mult.commute)
        hence 14:"both_member_options (Node (Some (mi, ma)) deg treeList summary) ?y"
          by (metis "07" "09" "4.hyps"(4) "4.hyps"(5) Suc_1 \<open>2 \<le> deg\<close> \<open>deg div 2 = n\<close> add_leD1 both_member_options_from_chilf_to_complete_tree plus_1_eq_Suc)
        have 15: "vebt_member (Node (Some (mi, ma)) deg treeList summary) ?y"
          using "14" thisvalid valid_member_both_member_options by blast
        have 16: "Some ?y = vebt_pred (Node (Some (mi, ma)) deg treeList summary) x"
          by (simp add: \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some (2 ^ (deg div 2) * high x (deg div 2) + predy)\<close>)
        have 17: "x = ?h * 2^(deg div 2) + ?l"
          using bit_concat_def bit_split_inv by auto
        have 18: "x - ?y =   ?h * 2^(deg div 2) + ?l -?h * 2^(deg div 2) - predy "
          by (metis "17" diff_diff_add mult.commute)
        hence 19: "?y < x"
          using "04" "17" mult.commute nat_add_left_cancel_less pred_member by fastforce
        have 20: "z < x \<Longrightarrow> vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<Longrightarrow> z\<le> ?y " for z
        proof-
          assume "z < x" and "vebt_member (Node (Some (mi, ma)) deg treeList summary) z"
          hence "high z (deg div 2) \<le> high x (deg div 2)"
            by (simp add: div_le_mono high_def)
          then show ?thesis
          proof(cases "high z (deg div 2) = high x (deg div 2)")
            case True
            hence 0000: "high z (deg div 2) = high x (deg div 2)" by simp
            then show ?thesis
            proof(cases "z = mi")
              case True
              then show ?thesis
                using "15" vebt_mint.simps(3) mint_corr_help thisvalid by blast
            next
              case False
              hence ad:"vebt_member (treeList ! ?h) (low z (deg div 2))"
                using vebt_member.simps(5)[of mi ma "deg-2" treeList summary z]
                by (metis True \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z\<close> \<open>x \<le> ma\<close> \<open>z < x\<close> leD member_inv)
              have "is_pred_in_set (set_vebt' (treeList ! ?h)) ?l predy"
                using "04" by blast
              have "low z (deg div 2) < ?l"
                by (metis (full_types) True \<open>z < x\<close> bit_concat_def bit_split_inv nat_add_left_cancel_less)
              hence "predy \<ge> low z (deg div 2)" using 04 ad unfolding is_pred_in_set_def
                by (simp add: set_vebt'_def)
              hence "?y \<ge> z"
                by (smt True bit_concat_def bit_split_inv diff_add_inverse diff_diff_add diff_is_0_eq mult.commute)
              then show ?thesis by blast
            qed
          next
            case False
            hence "high z (deg div 2) < high ?y (deg div 2)"
              using "10" \<open>high z (deg div 2) \<le> high x (deg div 2)\<close> by linarith
            then show ?thesis
              by (metis div_le_mono high_def nat_le_linear not_le)
          qed
        qed
        hence "is_pred_in_set (set_vebt' (Node (Some (mi, ma)) deg treeList summary)) x ?y"
          by (simp add: "15" "19" pred_member)
        then show ?thesis using 16
          by (metis eq_iff option.inject pred_member)
      next
        case False
        hence i1:"?minlow =  None \<or> \<not> (Some ?l >\<^sub>o  ?minlow)" by simp
        hence 2: "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =  (
                            if ?pr = None then (if x > mi
                                                then Some mi
                                                else None)
                             else Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr))"
          using "1" by auto
        have " invar_vebt (treeList ! ?h) n"
          by (metis "4"(1) True inthall member_def)
        hence 33:"\<nexists> u. vebt_member (treeList ! ?h) u \<and> u < ?l"
        proof(cases "?minlow = None")
          case True
          then show ?thesis using mint_corr_help_empty[of "treeList ! ?h" n]
            by (simp add: \<open>invar_vebt (treeList ! high x (deg div 2)) n\<close> set_vebt'_def)
        next
          case False
          obtain minilow where "?minlow =Some minilow"
            using False by blast
          hence "minilow \<ge> ?l"
            using "i1" by auto
          then show ?thesis
            by (meson \<open>vebt_mint (treeList ! high x (deg div 2)) = Some minilow\<close> \<open>invar_vebt (treeList ! high x (deg div 2)) n\<close> leD less_le_trans mint_corr_help)
        qed
        then show ?thesis
        proof(cases "?pr= None")
          case True
          hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =  (if x > mi then Some mi else  None)"
            by (simp add: "2")
          hence "\<nexists> i. is_pred_in_set (set_vebt' summary) ?h i"
            using "4.hyps"(3) True by force
          hence "\<nexists> i. i < ?h \<and> vebt_member summary i " using pred_none_empty[of "set_vebt' summary" ?h]
          proof -
            { fix nn :: nat
              have "\<forall>n. ((is_pred_in_set (Collect (vebt_member summary)) (high x (deg div 2)) esk1_0 \<or> infinite (Collect (vebt_member summary))) \<or> n \<notin> Collect (vebt_member summary)) \<or> \<not> n < high x (deg div 2)"
                using \<open>\<nexists>i. is_pred_in_set (set_vebt' summary) (high x (deg div 2)) i\<close> pred_none_empty set_vebt'_def by auto
              then have "\<not> nn < high x (deg div 2) \<or> \<not> vebt_member summary nn"
                by (metis (no_types) "4.hyps"(2) \<open>\<nexists>i. is_pred_in_set (set_vebt' summary) (high x (deg div 2)) i\<close> mem_Collect_eq set_vebt'_def set_vebt_finite) }
            then show ?thesis
              by blast
          qed
          then show ?thesis
          proof(cases "x > mi")
            case True
            hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some mi"
              by (simp add: \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = (if mi < x then Some mi else None)\<close>)
            have "(vebt_member (Node (Some (mi, ma)) deg treeList summary) z  \<and> z < x \<and> z > mi) \<Longrightarrow> False" for z
            proof-
              assume "vebt_member (Node (Some (mi, ma)) deg treeList summary) z  \<and> z < x \<and> z > mi"
              hence "vebt_member ( treeList ! (high z (deg div 2))) (low z (deg div 2))"
                using \<open>x \<le> ma\<close> member_inv not_le by blast
              moreover hence "high z (deg div 2) < 2^m"
                using "4.hyps"(4) \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> \<open>x \<le> ma\<close> member_inv by fastforce
              moreover hence "invar_vebt (treeList ! (high z (deg div 2))) n" using 4(1)
                by (simp add: "4.hyps"(4))
              ultimately have "vebt_member summary (high z (deg div 2))" using 4(7)
                using "4.hyps"(2) both_member_options_equiv_member by blast
              have "(high z (deg div 2)) \<le> ?h"
                by (simp add: \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> div_le_mono high_def less_or_eq_imp_le)
              then show False
                by (metis "33" \<open>\<not> (\<exists>i<high x (deg div 2). vebt_member summary i)\<close> \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> \<open>vebt_member (treeList ! high z (deg div 2)) (low z (deg div 2))\<close> \<open>vebt_member summary (high z (deg div 2))\<close> bit_concat_def bit_split_inv le_neq_implies_less nat_add_left_cancel_less)
            qed
            hence "is_pred_in_set (set_vebt' ((Node (Some (mi, ma)) deg treeList summary))) x mi"
              by (metis VEBT_Member.vebt_member.simps(5) True \<open>2 \<le> deg\<close> add_2_eq_Suc le_add_diff_inverse le_less_linear pred_member)
            then show ?thesis
              by (metis \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some mi\<close> \<open>x \<le> ma\<close> option.sel leD member_inv pred_member)
          next
            case False
            hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = None"
              by (simp add: "2" True)
            then show ?thesis
              by (metis (full_types) False less_trans member_inv option.distinct(1) pred_max pred_member)
          qed
        next
          case False
          hence fst:"vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =
                    Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr)"
            using "2" by presburger
          obtain pr where "?pr = Some pr"
            using False by blast
          hence "is_pred_in_set (set_vebt' summary) ?h pr"
            using "4.hyps"(3) by blast
          hence "vebt_member summary pr"
            using pred_member by blast
          hence "both_member_options summary pr"
            using "4.hyps"(2) both_member_options_equiv_member by auto
          hence "pr < 2^m"
            using "4.hyps"(2) \<open>vebt_member summary pr\<close> member_bound by blast
          hence "\<exists> maxy. both_member_options (treeList ! pr) maxy"
            using "4.hyps"(7) \<open>both_member_options summary pr\<close> by blast
          hence fgh:"set_vebt' (treeList ! pr) \<noteq> {}"
            by (metis "4.hyps"(1) "4.hyps"(2) "4.hyps"(4) \<open>vebt_member summary pr\<close> empty_Collect_eq member_bound nth_mem set_vebt'_def valid_member_both_member_options)
          hence "invar_vebt (treeList ! the ?pr) n"
            by (simp add: "4.hyps"(1) "4.hyps"(4) \<open>pr < 2 ^ m\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close>)
          then obtain maxy where "Some maxy = vebt_maxt (treeList ! pr)"
            by (metis \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> fgh option.sel vebt_maxt.elims maxt_corr_help_empty)
          hence "Some maxy = vebt_maxt (treeList ! the ?pr)"
            by (simp add: \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close>)
          hence "max_in_set (set_vebt' (treeList ! the ?pr)) maxy"
            using \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> maxt_corr by auto
          hence scmem:"vebt_member (treeList ! the ?pr) maxy"
            using \<open>Some maxy = vebt_maxt (treeList ! the (vebt_pred summary (high x (deg div 2))))\<close> \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> maxt_member by force
          let ?res =  "Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr)"
          obtain res where snd: "res = the ?res" by blast
          hence "res = 2^(deg div 2) * pr + maxy"
            by (metis \<open>Some maxy = vebt_maxt (treeList ! pr)\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> add_def option.sel mul_def option_shift.simps(3))
          have "high res (deg div 2) = pr"
            by (metis \<open>deg div 2 = n\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> \<open>invar_vebt (treeList ! the ?pr) n\<close> high_inv member_bound mult.commute scmem)
          hence "res < x"
            by (metis \<open>is_pred_in_set (set_vebt' summary) (high x (deg div 2)) pr\<close> div_le_mono high_def pred_member verit_comp_simplify1(3))
          have "both_member_options (treeList ! (high res (deg div 2))) (low res (deg div 2))"
            by (metis \<open>deg div 2 = n\<close> \<open>high res (deg div 2) = pr\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> both_member_options_equiv_member option.sel low_inv member_bound mult.commute scmem)
          have "both_member_options (Node (Some (mi, ma)) deg treeList summary) res"
            by (metis "4.hyps"(2) "4.hyps"(4) "4.hyps"(6) \<open>1 \<le> n\<close> \<open>both_member_options (treeList ! high res (deg div 2)) (low res (deg div 2))\<close> \<open>high res (deg div 2) = pr\<close> \<open>vebt_member summary pr\<close> both_member_options_from_chilf_to_complete_tree member_bound trans_le_add1)
          hence "vebt_member (Node (Some (mi, ma)) deg treeList summary) res"
            using thisvalid valid_member_both_member_options by auto
          hence "res > mi"
            by (metis "4.hyps"(11) \<open>both_member_options (treeList ! high res (deg div 2)) (low res (deg div 2))\<close> \<open>deg div 2 = n\<close> \<open>high res (deg div 2) = pr\<close> \<open>pr < 2 ^ m\<close> \<open>res < x\<close> \<open>x \<le> ma\<close> less_le_trans member_inv)
          hence "res < ma"
            using \<open>res < x\<close> \<open>x \<le> ma\<close> less_le_trans by blast
          have "(vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x) \<Longrightarrow> z \<le> res" for z
          proof-
            fix z
            assume "vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x"
            hence 20: "z = mi \<or> z = ma \<or> (high z (deg div 2) < length treeList
                                    \<and> vebt_member ( treeList ! (high z (deg div 2))) (low z (deg div 2)))" using
              vebt_member.simps(5)[of mi ma "deg-2" treeList summary z]
              using member_inv by blast
            have "z \<noteq> ma"
              using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> \<open>x \<le> ma\<close> leD by blast
            hence "mi \<noteq> ma"
              by (metis \<open>mi < res\<close> \<open>res < x\<close> \<open>x \<le> ma\<close> leD less_trans)
            hence "z < 2^deg"
              using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> member_bound thisvalid by blast
            hence abc:"invar_vebt (treeList ! (high z (deg div 2))) n"
              by (metis "4.hyps"(1) "4.hyps"(2) "4.hyps"(5) "4.hyps"(6) \<open>deg div 2 = n\<close> \<open>z < 2 ^ deg\<close> \<open>length treeList = 2 ^ n\<close> deg_not_0 exp_split_high_low(1) in_set_member inthall)
            then show "z \<le> res"
            proof(cases "z = mi")
              case True
              then show ?thesis
                using \<open>mi < res\<close> by auto
            next
              case False
              hence abe:"vebt_member( treeList ! (high z (deg div 2))) (low z (deg div 2))"
                using "20" \<open>z \<noteq> ma\<close> by blast
              hence abh:"vebt_member summary (high z (deg div 2))"
                by (metis "20" "4.hyps"(2) "4.hyps"(4) "4.hyps"(7) False \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> \<open>x \<le> ma\<close> abc both_member_options_equiv_member not_le)
              have aaa:"(high z (deg div 2)) = (high x (deg div 2)) \<Longrightarrow> vebt_member (treeList ! ?h) (low z (deg div 2))"
                using abe by auto
              have "high z(deg div 2) > pr \<Longrightarrow> False"
              proof-
                assume "high z(deg div 2) > pr"
                hence "vebt_member summary (high z(deg div 2))"
                  using abh by blast
                have aaaa:"?h \<le> high z(deg div 2)"
                  by (meson \<open>is_pred_in_set (set_vebt' summary) (high x (deg div 2)) pr\<close> \<open>pr < high z (deg div 2)\<close> abh leD not_le_imp_less pred_member)
                have bbbb:"?h \<ge> high z(deg div 2)"
                  by (simp add: \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> div_le_mono dual_order.strict_implies_order high_def)
                hence "?h = high z (deg div 2)"
                  using aaaa eq_iff by blast
                hence "vebt_member (treeList ! ?h) (low z (deg div 2))"
                  using aaa by linarith
                hence "(low z (deg div 2)) < ?l"
                  by (metis \<open>high x (deg div 2) = high z (deg div 2)\<close> \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> add_le_cancel_left div_mult_mod_eq high_def less_le low_def)
                then show False
                  using "33" \<open>vebt_member (treeList ! high x (deg div 2)) (low z (deg div 2))\<close> by blast
              qed
              hence "high z(deg div 2) \<le> pr"
                using not_less by blast
              then show " z \<le> res"
              proof(cases "high z(deg div 2) = pr")
                case True
                hence "vebt_member (treeList ! (high z(deg div 2))) (low z (deg div 2))"
                  using abe by blast
                have "low z (deg div 2) \<le> maxy"
                  using True \<open>Some maxy = vebt_maxt (treeList ! pr)\<close> abc abe maxt_corr_help by auto
                hence "z \<le> res"
                  by (metis True \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> add_le_cancel_left div_mult_mod_eq high_def low_def mult.commute)
                then show ?thesis by simp
              next
                case False
                hence "high z(deg div 2) < pr"
                  by (simp add: \<open>high z (deg div 2) \<le> pr\<close> less_le)
                then show ?thesis
                  by (metis \<open>high res (deg div 2) = pr\<close> div_le_mono high_def leD linear)
              qed
            qed
          qed
          hence "is_pred_in_set (set_vebt' (Node (Some (mi, ma)) deg treeList summary)) x res"
            using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) res\<close> \<open>res < x\<close> pred_member by presburger
          then show ?thesis using fst snd
            by (metis \<open>Some maxy = vebt_maxt (treeList ! the (vebt_pred summary (high x (deg div 2))))\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> add_shift dual_order.eq_iff mul_shift pred_member)
        qed
      qed
    next
      case False
      then show ?thesis
        by (metis "4.hyps"(10) "4.hyps"(5) "4.hyps"(6) \<open>1 \<le> n\<close> \<open>deg div 2 = n\<close> \<open>length treeList = 2 ^ n\<close> \<open>x \<le> ma\<close> exp_split_high_low(1) le_less_trans le_neq_implies_less not_less not_less_zero zero_neq_one)
    qed
  qed
next
  case (5 treeList n summary m deg mi ma)
  hence "Suc n = m"  and "deg = n + m" and "length treeList = 2^m \<and> invar_vebt summary m"
    by blast +
  hence "n \<ge> 1"
    using "5.hyps"(1) set_n_deg_not_0 by blast
  hence "deg \<ge> 2"
    by (simp add: "5.hyps"(5) "5.hyps"(6))
  hence "deg div 2 =n"
    by (simp add: "5.hyps"(5) "5.hyps"(6))
  moreover hence thisvalid:"invar_vebt (Node (Some (mi, ma)) deg treeList summary) deg"
    using 5 invar_vebt.intros(5)[of treeList n summary m]  by blast
  ultimately have "deg div 2 =n" by simp
  then show ?case
  proof(cases "x > ma")
    case True
    hence 0: "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some ma"
      by (simp add: \<open>2 \<le> deg\<close> pred_max)
    have 1:"ma = the (vebt_maxt (Node (Some (mi, ma)) deg treeList summary))" by simp
    hence "ma \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary)"
      by (metis VEBT_Member.vebt_member.simps(5) \<open>2 \<le> deg\<close> add_numeral_left arith_simps(1) le_add_diff_inverse mem_Collect_eq numerals(1) plus_1_eq_Suc set_vebt'_def)
    hence 2:"y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary) \<Longrightarrow> y \<le> x" for y
      using "5.hyps"(9) True member_inv set_vebt'_def by fastforce
    hence 3: "y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary) \<Longrightarrow> (y < ma \<Longrightarrow> y \<le> x)" for y by blast
    hence 4: "\<forall> y \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary). y < ma \<longrightarrow> y \<le> x" by blast
    hence "is_pred_in_set (set_vebt' (Node (Some (mi, ma)) deg treeList summary)) x ma"
      by (metis "5.hyps"(9) True \<open>ma \<in> set_vebt' (Node (Some (mi, ma)) deg treeList summary)\<close> less_or_eq_imp_le mem_Collect_eq member_inv pred_member set_vebt'_def)
    then show ?thesis
      by (metis "0" option.sel leD le_less_Suc_eq not_less_eq pred_member)
  next
    case False
    hence "x \<le> ma"by simp
    then show ?thesis
    proof(cases "high x (deg div 2)< length treeList ")
      case True
      hence "high x n < 2^m \<and> low x n < 2^n"
        by (simp add: \<open>deg div 2 = n\<close> \<open>length treeList = 2 ^ m\<close> low_def)
      let ?l = "low x (deg div 2)"
      let ?h = "high x (deg div 2)"
      let ?minlow = "vebt_mint (treeList ! ?h)"
      let ?pr = "vebt_pred summary ?h"
      have 1:"vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =
                           (if ?minlow \<noteq> None \<and> (Some ?l >\<^sub>o  ?minlow) then
                                                    Some (2^(deg div 2)) *\<^sub>o Some ?h +\<^sub>o vebt_pred (treeList ! ?h) ?l
                             else let pr = vebt_pred summary ?h in
                             if pr = None then (if x > mi then Some mi else None)
                             else Some (2^(deg div 2)) *\<^sub>o pr +\<^sub>o vebt_maxt (treeList ! the pr) )"
        by (smt True \<open>2 \<le> deg\<close> \<open>x \<le> ma\<close> pred_less_length_list)
      then show ?thesis
      proof(cases "?minlow \<noteq> None \<and> (Some ?l >\<^sub>o  ?minlow)")
        case True
        then obtain minl where 00:"(Some minl = ?minlow) \<and> ?l > minl" by auto
        have 01:"invar_vebt ((treeList ! ?h)) n \<and> (treeList ! ?h) \<in> set treeList "
          by (metis "5.hyps"(1) \<open>deg div 2 = n\<close> \<open>high x n < 2 ^ m \<and> low x n < 2 ^ n\<close> \<open>length treeList = 2 ^ m \<and> invar_vebt summary m\<close> inthall member_def)
        have  02:"vebt_member ((treeList ! ?h)) minl"
          using "00" "01" mint_member by auto
        hence 03: "\<exists> y. y < ?l \<and> vebt_member ((treeList ! ?h)) y"
          using "00" by blast
        hence afinite: "finite (set_vebt' (treeList ! ?h)) "
          using "01" set_vebt_finite by blast
        then obtain predy where 04:"is_pred_in_set (set_vebt' (treeList ! ?h)) ?l predy"
          using "00" "01" mint_corr obtain_set_pred by fastforce
        hence 05:"Some predy =  vebt_pred (treeList ! ?h) ?l"  using 5(1) 01 by force
        hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x  =  Some (2^(deg div 2)*  ?h + predy) "
          by (metis "1" True add_def mul_def option_shift.simps(3))
        hence 06: "predy \<in> set_vebt' (treeList ! ?h)"
          using "04" is_pred_in_set_def by blast
        hence 07: "predy < 2^(deg div 2) \<and> ?h < 2^(deg div 2 +1) \<and> deg div 2 + deg div 2 +1 = deg"
          using "04" "5.hyps"(5) "5.hyps"(6) \<open>high x n < 2 ^ m \<and> low x n < 2 ^ n\<close> pred_member by force
        let ?y = "2^(deg div 2)*  ?h + predy"
        have 08: "vebt_member (treeList ! ?h) predy"
          using "06" set_vebt'_def by auto
        hence 09: "both_member_options (treeList ! ?h) predy"
          using "01" both_member_options_equiv_member by blast
        have 10: "high ?y (deg div 2) = ?h \<and> low ?y (deg div 2) = predy"
          by (simp add: "07" high_inv low_inv mult.commute)
        hence 14:"both_member_options (Node (Some (mi, ma)) deg treeList summary) ?y"
          using "07" "09" "5.hyps"(4) \<open>deg div 2 = n\<close> \<open>high x n < 2 ^ m \<and> low x n < 2 ^ n\<close> both_member_options_from_chilf_to_complete_tree by auto
        have 15: "vebt_member (Node (Some (mi, ma)) deg treeList summary) ?y"
          using "14" thisvalid valid_member_both_member_options by blast
        have 16: "Some ?y = vebt_pred (Node (Some (mi, ma)) deg treeList summary) x"
          by (simp add: \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some (2 ^ (deg div 2) * high x (deg div 2) + predy)\<close>)
        have 17: "x = ?h * 2^(deg div 2) + ?l"
          using bit_concat_def bit_split_inv by auto
        have 18: "x - ?y =   ?h * 2^(deg div 2) + ?l -?h * 2^(deg div 2) - predy "
          by (metis "17" diff_diff_add mult.commute)
        hence 19: "?y < x"
          using "04" "17" mult.commute nat_add_left_cancel_less pred_member by fastforce
        have 20: "z < x \<Longrightarrow> vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<Longrightarrow> z\<le> ?y " for z
        proof-
          assume "z < x" and "vebt_member (Node (Some (mi, ma)) deg treeList summary) z"
          hence "high z (deg div 2) \<le> high x (deg div 2)"
            by (simp add: div_le_mono high_def)
          then show ?thesis
          proof(cases "high z (deg div 2) = high x (deg div 2)")
            case True
            hence 0000: "high z (deg div 2) = high x (deg div 2)" by simp
            then show ?thesis
            proof(cases "z = mi")
              case True
              then show ?thesis
                by (metis "15" "5.hyps"(9) add.left_neutral le_add2 less_imp_le_nat member_inv)
            next
              case False
              hence ad:"vebt_member (treeList ! ?h) (low z (deg div 2))"
                using vebt_member.simps(5)[of mi ma "deg-2" treeList summary z]
                by (metis True \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z\<close> \<open>x \<le> ma\<close> \<open>z < x\<close> leD member_inv)
              have "is_pred_in_set (set_vebt' (treeList ! ?h)) ?l predy"
                using "04" by blast
              have "low z (deg div 2) < ?l"
                by (metis (full_types) True \<open>z < x\<close> bit_concat_def bit_split_inv nat_add_left_cancel_less)
              hence "predy \<ge> low z (deg div 2)" using 04 ad unfolding is_pred_in_set_def
                by (simp add: set_vebt'_def)
              hence "?y \<ge> z"
                by (smt True bit_concat_def bit_split_inv diff_add_inverse diff_diff_add diff_is_0_eq mult.commute)
              then show ?thesis by blast
            qed
          next
            case False
            hence "high z (deg div 2) < high ?y (deg div 2)"
              using "10" \<open>high z (deg div 2) \<le> high x (deg div 2)\<close> by linarith
            then show ?thesis
              by (metis div_le_mono high_def nat_le_linear not_le)
          qed
        qed
        hence "is_pred_in_set (set_vebt'(Node (Some (mi, ma)) deg treeList summary)) x ?y"
          by (simp add: "15" "19" pred_member)
        then show ?thesis using 16
          by (metis eq_iff option.inject pred_member)
      next
        case False
        hence i1:"?minlow =  None \<or> \<not> (Some ?l >\<^sub>o  ?minlow)" by simp
        hence 2: "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =  (
                            if ?pr = None then (if x > mi
                                                then Some mi
                                                else None)
                             else Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr))"
          using "1" by auto
        have " invar_vebt (treeList ! ?h) n"
          by (metis "5"(1) True inthall member_def)
        hence 33:"\<nexists> u. vebt_member (treeList ! ?h) u \<and> u < ?l"
        proof(cases "?minlow = None")
          case True
          then show ?thesis using mint_corr_help_empty[of "treeList ! ?h" n]
            by (simp add: \<open>invar_vebt (treeList ! high x (deg div 2)) n\<close> set_vebt'_def)
        next
          case False
          obtain minilow where "?minlow =Some minilow"
            using False by blast
          hence "minilow \<ge> ?l"
            using "i1" by auto
          then show ?thesis
            by (meson \<open>vebt_mint (treeList ! high x (deg div 2)) = Some minilow\<close> \<open>invar_vebt (treeList ! high x (deg div 2)) n\<close> leD less_le_trans mint_corr_help)
        qed
        then show ?thesis
        proof(cases "?pr= None")
          case True
          hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =  (if x > mi then Some mi else  None)"
            by (simp add: "2")
          hence "\<nexists> i. is_pred_in_set (set_vebt' summary) ?h i"
            using "5.hyps"(3) True by force
          hence "\<nexists> i. i < ?h \<and> vebt_member summary i " using pred_none_empty[of "set_vebt' summary" ?h]
          proof -
            { fix nn :: nat
              have "\<forall>n. ((is_pred_in_set (Collect (vebt_member summary)) (high x (deg div 2)) esk1_0 \<or> infinite (Collect (vebt_member summary))) \<or> n \<notin> Collect (vebt_member summary)) \<or> \<not> n < high x (deg div 2)"
                using \<open>\<nexists>i. is_pred_in_set (set_vebt' summary) (high x (deg div 2)) i\<close> pred_none_empty set_vebt'_def by auto
              then have "\<not> nn < high x (deg div 2) \<or> \<not> vebt_member summary nn"
                by (metis (no_types) "5.hyps"(2) \<open>\<nexists>i. is_pred_in_set (set_vebt' summary) (high x (deg div 2)) i\<close> mem_Collect_eq set_vebt'_def set_vebt_finite) }
            then show ?thesis
              by blast
          qed
          then show ?thesis
          proof(cases "x > mi")
            case True
            hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some mi"
              by (simp add: \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = (if mi < x then Some mi else None)\<close>)
            have "(vebt_member (Node (Some (mi, ma)) deg treeList summary) z  \<and> z < x \<and> z > mi) \<Longrightarrow> False" for z
            proof-
              assume "vebt_member (Node (Some (mi, ma)) deg treeList summary) z  \<and> z < x \<and> z > mi"
              hence "vebt_member ( treeList ! (high z (deg div 2))) (low z (deg div 2))"
                using \<open>x \<le> ma\<close> member_inv not_le by blast
              moreover hence "high z (deg div 2) < 2^m"
                using "5.hyps"(4) \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> \<open>x \<le> ma\<close> member_inv by fastforce
              moreover hence "invar_vebt (treeList ! (high z (deg div 2))) n" using 5(1)
                by (simp add: "5.hyps"(4))
              ultimately have "vebt_member summary (high z (deg div 2))" using 5(7)
                using "5.hyps"(2) both_member_options_equiv_member by blast
              have "(high z (deg div 2)) \<le> ?h"
                by (simp add: \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> div_le_mono high_def less_or_eq_imp_le)
              then show False
                by (metis "33" \<open>\<not> (\<exists>i<high x (deg div 2). vebt_member summary i)\<close> \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x \<and> mi < z\<close> \<open>vebt_member (treeList ! high z (deg div 2)) (low z (deg div 2))\<close> \<open>vebt_member summary (high z (deg div 2))\<close> bit_concat_def bit_split_inv le_neq_implies_less nat_add_left_cancel_less)
            qed
            hence "is_pred_in_set (set_vebt' ((Node (Some (mi, ma)) deg treeList summary))) x mi"
              by (metis VEBT_Member.vebt_member.simps(5) True \<open>2 \<le> deg\<close> add_2_eq_Suc le_add_diff_inverse le_less_linear pred_member)
            then show ?thesis
              by (metis \<open>vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = Some mi\<close> \<open>x \<le> ma\<close> option.sel leD member_inv pred_member)
          next
            case False
            hence "vebt_pred (Node (Some (mi, ma)) deg treeList summary) x = None"
              by (simp add: "2" True)
            then show ?thesis
              by (metis (full_types) False less_trans member_inv option.distinct(1) pred_max pred_member)
          qed
        next
          case False
          hence fst:"vebt_pred (Node (Some (mi, ma)) deg treeList summary) x =
                    Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr)"
            using "2" by presburger
          obtain pr where "?pr = Some pr"
            using False by blast
          hence "is_pred_in_set (set_vebt' summary) ?h pr"
            using "5.hyps"(3) by blast
          hence "vebt_member summary pr"
            using pred_member by blast
          hence "both_member_options summary pr"
            using "5.hyps"(2) both_member_options_equiv_member by auto
          hence "pr < 2^m"
            using "5.hyps"(2) \<open>vebt_member summary pr\<close> member_bound by blast
          hence "\<exists> maxy. both_member_options (treeList ! pr) maxy"
            using "5.hyps"(7) \<open>both_member_options summary pr\<close> by blast
          hence fgh:"set_vebt' (treeList ! pr) \<noteq> {}"
            by (metis "5.hyps"(1) "5.hyps"(4) Collect_empty_eq \<open>pr < 2 ^ m\<close> nth_mem set_vebt'_def valid_member_both_member_options)
          hence "invar_vebt (treeList ! the ?pr) n"
            by (simp add: "5.hyps"(1) "5.hyps"(4) \<open>pr < 2 ^ m\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close>)
          then obtain maxy where "Some maxy = vebt_maxt (treeList ! pr)"
            by (metis \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> fgh option.sel vebt_maxt.elims maxt_corr_help_empty)
          hence "Some maxy = vebt_maxt (treeList ! the ?pr)"
            by (simp add: \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close>)
          hence "max_in_set (set_vebt' (treeList ! the ?pr)) maxy"
            using \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> maxt_corr by auto
          hence scmem:"vebt_member (treeList ! the ?pr) maxy"
            using \<open>Some maxy = vebt_maxt (treeList ! the (vebt_pred summary (high x (deg div 2))))\<close> \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> maxt_member by force
          let ?res =  "Some (2^(deg div 2)) *\<^sub>o ?pr +\<^sub>o vebt_maxt (treeList ! the ?pr)"
          obtain res where snd: "res = the ?res" by blast
          hence "res = 2^(deg div 2) * pr + maxy"
            by (metis \<open>Some maxy = vebt_maxt (treeList ! pr)\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> add_def option.sel mul_def option_shift.simps(3))
          have "high res (deg div 2) = pr"
            by (metis \<open>deg div 2 = n\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> \<open>invar_vebt (treeList ! the ?pr) n\<close> high_inv member_bound mult.commute scmem)
          hence "res < x"
            by (metis \<open>is_pred_in_set (set_vebt' summary) (high x (deg div 2)) pr\<close> div_le_mono high_def pred_member verit_comp_simplify1(3))
          have "both_member_options (treeList ! (high res (deg div 2))) (low res (deg div 2))"
            by (metis \<open>deg div 2 = n\<close> \<open>high res (deg div 2) = pr\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> \<open>invar_vebt (treeList ! the (vebt_pred summary (high x (deg div 2)))) n\<close> both_member_options_equiv_member option.sel low_inv member_bound mult.commute scmem)
          have "both_member_options (Node (Some (mi, ma)) deg treeList summary) res"
            by (metis "5.hyps"(2) "5.hyps"(4) "5.hyps"(6) \<open>1 \<le> n\<close> \<open>both_member_options (treeList ! high res (deg div 2)) (low res (deg div 2))\<close> \<open>high res (deg div 2) = pr\<close> \<open>vebt_member summary pr\<close> both_member_options_from_chilf_to_complete_tree member_bound trans_le_add1)
          hence "vebt_member (Node (Some (mi, ma)) deg treeList summary) res"
            using thisvalid valid_member_both_member_options by auto
          hence "res > mi"
            by (metis "5.hyps"(11) \<open>both_member_options (treeList ! high res (deg div 2)) (low res (deg div 2))\<close> \<open>deg div 2 = n\<close> \<open>high res (deg div 2) = pr\<close> \<open>pr < 2 ^ m\<close> \<open>res < x\<close> \<open>x \<le> ma\<close> less_le_trans member_inv)
          hence "res < ma"
            using \<open>res < x\<close> \<open>x \<le> ma\<close> less_le_trans by blast
          have "(vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x) \<Longrightarrow> z \<le> res" for z
          proof-
            fix z
            assume "vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x"
            hence 20: "z = mi \<or> z = ma \<or> (high z (deg div 2) < length treeList
                                    \<and> vebt_member ( treeList ! (high z (deg div 2))) (low z (deg div 2)))" using
              vebt_member.simps(5)[of mi ma "deg-2" treeList summary z]
              using member_inv by blast
            have "z \<noteq> ma"
              using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> \<open>x \<le> ma\<close> leD by blast
            hence "mi \<noteq> ma"
              by (metis \<open>mi < res\<close> \<open>res < x\<close> \<open>x \<le> ma\<close> leD less_trans)
            hence "z < 2^deg"
              using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> member_bound thisvalid by blast
            hence "(high z (deg div 2)) <2^m"
              by (metis "5.hyps"(5) "5.hyps"(6) \<open>1 \<le> n\<close> \<open>deg div 2 = n\<close> exp_split_high_low(1) less_le_trans numeral_One zero_less_Suc zero_less_numeral)
            hence abc:"invar_vebt (treeList ! (high z (deg div 2))) n"
              by (simp add: "5.hyps"(1) "5.hyps"(4))
            then show "z \<le> res"
            proof(cases "z = mi")
              case True
              then show ?thesis
                using \<open>mi < res\<close> by auto
            next
              case False
              hence abe:"vebt_member( treeList ! (high z (deg div 2))) (low z (deg div 2))"
                using "20" \<open>z \<noteq> ma\<close> by blast
              hence abh:"vebt_member summary (high z (deg div 2))"
                using "5.hyps"(7) \<open>high z (deg div 2) < 2 ^ m\<close> \<open>length treeList = 2 ^ m \<and> invar_vebt summary m\<close> abc both_member_options_equiv_member by blast
              have aaa:"(high z (deg div 2)) = (high x (deg div 2)) \<Longrightarrow> vebt_member (treeList ! ?h) (low z (deg div 2))"
                using abe by auto
              have "high z(deg div 2) > pr \<Longrightarrow> False"
              proof-
                assume "high z(deg div 2) > pr"
                hence "vebt_member summary (high z(deg div 2))"
                  using abh by blast
                have aaaa:"?h \<le> high z(deg div 2)"
                  by (meson \<open>is_pred_in_set (set_vebt' summary) (high x (deg div 2)) pr\<close> \<open>pr < high z (deg div 2)\<close> abh leD not_le_imp_less pred_member)
                have bbbb:"?h \<ge> high z(deg div 2)"
                  by (simp add: \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> div_le_mono dual_order.strict_implies_order high_def)
                hence "?h = high z (deg div 2)"
                  using aaaa eq_iff by blast
                hence "vebt_member (treeList ! ?h) (low z (deg div 2))"
                  using aaa by linarith
                hence "(low z (deg div 2)) < ?l"
                  by (metis \<open>high x (deg div 2) = high z (deg div 2)\<close> \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) z \<and> z < x\<close> add_le_cancel_left div_mult_mod_eq high_def less_le low_def)
                then show False
                  using "33" \<open>vebt_member (treeList ! high x (deg div 2)) (low z (deg div 2))\<close> by blast
              qed
              hence "high z(deg div 2) \<le> pr"
                using not_less by blast
              then show " z \<le> res"
              proof(cases "high z(deg div 2) = pr")
                case True
                hence "vebt_member (treeList ! (high z(deg div 2))) (low z (deg div 2))"
                  using abe by blast
                have "low z (deg div 2) \<le> maxy"
                  using True \<open>Some maxy = vebt_maxt (treeList ! pr)\<close> abc abe maxt_corr_help by auto
                hence "z \<le> res"
                  by (metis True \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> add_le_cancel_left div_mult_mod_eq high_def low_def mult.commute)
                then show ?thesis by simp
              next
                case False
                hence "high z(deg div 2) < pr"
                  by (simp add: \<open>high z (deg div 2) \<le> pr\<close> less_le)
                then show ?thesis
                  by (metis \<open>high res (deg div 2) = pr\<close> div_le_mono high_def leD linear)
              qed
            qed
          qed
          hence "is_pred_in_set (set_vebt' (Node (Some (mi, ma)) deg treeList summary)) x res"
            using \<open>vebt_member (Node (Some (mi, ma)) deg treeList summary) res\<close> \<open>res < x\<close> pred_member by presburger
          then show ?thesis using fst snd
            by (metis \<open>Some maxy = vebt_maxt (treeList ! the (vebt_pred summary (high x (deg div 2))))\<close> \<open>vebt_pred summary (high x (deg div 2)) = Some pr\<close> \<open>res = 2 ^ (deg div 2) * pr + maxy\<close> add_shift dual_order.eq_iff mul_shift pred_member)
        qed
      qed
    next
      case False
      then show ?thesis
        by (metis "5.hyps"(10) "5.hyps"(4) "5.hyps"(5) "5.hyps"(6) \<open>1 \<le> n\<close> \<open>deg div 2 = n\<close> \<open>x \<le> ma\<close> exp_split_high_low(1) le_0_eq le_less_trans verit_comp_simplify1(3) zero_less_Suc zero_neq_one)
    qed
  qed
qed

corollary pred_empty: assumes "invar_vebt t n "
  shows " (vebt_pred t x = None) = ({y. vebt_member t y \<and> y < x} = {})"
proof
  show " vebt_pred t x = None \<Longrightarrow> {y. vebt_member t y \<and> x > y} = {}"
  proof
    show "vebt_pred t x = None \<Longrightarrow> {y. vebt_member t y \<and> x > y} \<subseteq> {}"
    proof-
      assume "vebt_pred t x = None"
      hence "\<nexists> y. is_pred_in_set (set_vebt' t) x y"
        using assms pred_corr by force
      moreover hence "is_pred_in_set (set_vebt' t) x y \<Longrightarrow> vebt_member t y \<and> x < y " for y by auto
      ultimately show "{y. vebt_member t y \<and> x > y} \<subseteq> {}"
        using assms pred_none_empty set_vebt'_def set_vebt_finite by auto
    qed
    show " vebt_pred t x = None \<Longrightarrow> {} \<subseteq> {y. vebt_member t y \<and> x > y}" by simp
  qed
  show " {y. vebt_member t y \<and> x > y} = {} \<Longrightarrow> vebt_pred t x = None"
  proof-
    assume "{y. vebt_member t y \<and> x > y} = {} "
    hence "is_pred_in_set (set_vebt' t) x y \<Longrightarrow> False" for y
      using pred_member by auto
    thus "vebt_pred t x  = None"
      by (meson assms option_shift.elims pred_corr)
  qed
qed

theorem pred_correct: "invar_vebt t n \<Longrightarrow> vebt_pred t x = Some sx \<longleftrightarrow>is_pred_in_set (set_vebt t) x sx"
  by (simp add: pred_corr set_vebt_set_vebt'_valid)

lemma helpypredd:"invar_vebt t n \<Longrightarrow> vebt_pred t x = Some y \<Longrightarrow> y < 2^n"
  using member_bound pred_corr pred_member by blast

lemma "invar_vebt t n \<Longrightarrow> vebt_pred t x = Some y \<Longrightarrow> y < x"
  by (simp add: pred_corr pred_member)

end
end


theory GabrielaLimonta
imports "~~/src/HOL/IMP/AExp"
begin
(** Score: 15/10 *)
(* Homework 2.1 *)
datatype bst = Leaf | node int bst bst

fun \<alpha> :: "bst \<Rightarrow> (int) set" where
  "\<alpha> Leaf = {}"
| "\<alpha> (node e l r) = {e} \<union> \<alpha> l \<union> \<alpha> r"

value "\<alpha> (node 4 (node 2 (node 1 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"

fun invar :: "bst \<Rightarrow> bool" where
  "invar Leaf = True"
| "invar (node e l r) = (invar l \<and> invar r \<and> (\<forall>x\<in>(\<alpha> l). e > x) \<and> (\<forall>x\<in>(\<alpha> r). e < x)) "

value "invar (node 4 (node 2 (node 1 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"
value "invar (node 4 (node 1 (node 2 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"

fun lookup :: "int \<Rightarrow> bst \<Rightarrow> bool" where
  "lookup e Leaf = False"
| "lookup e (node x l r) = (if e = x then True else (if e > x then lookup e r else lookup e l))"

value "lookup 1 Leaf"
value "lookup 1 (node 1 Leaf Leaf)"
value "lookup 1 (node 2 Leaf Leaf)"
value "lookup 1 (node 4 (node 2 (node 1 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"
value "lookup 42 (node 4 (node 2 (node 1 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"
value "lookup 2 (node 4 (node 1 (node 2 Leaf Leaf) (node 3 Leaf Leaf)) (node 5 Leaf Leaf))"

lemma "invar t \<Longrightarrow> lookup x t \<longleftrightarrow> x\<in>\<alpha> t"
  apply(induction t)
  apply(auto)
  done

fun ins :: "int \<Rightarrow> bst \<Rightarrow> bst" where
  "ins e Leaf = (node e Leaf Leaf)"
| "ins e (node x l r) = (if e = x then node x l r else (if e < x then node x (ins e l) r else node x l (ins e r)))"

value "ins -4(ins -9(ins 5(ins 6(ins 56(ins 9(ins 3(ins 1 Leaf)))))))"

lemma ins_correct1: "\<lbrakk>invar t\<rbrakk> \<Longrightarrow> \<alpha> (ins x t) = insert x (\<alpha> t)"
  apply(induction t)
  apply(auto)
  done

lemma ins_correct2: "invar t \<Longrightarrow> invar (ins x t)"
  apply(induction t)
  apply(auto simp add: ins_correct1)
  done

fun dell :: "int \<Rightarrow> bst \<Rightarrow> bst" where
  "dell _ Leaf = Leaf"
| "dell e (node x l r) = (if e = x then (node x Leaf r) else (if e < x then (node x (dell e l) r) else (dell e r)))"

value "dell 5 (node 4 (node 2 (node 1 Leaf Leaf) (node 3 Leaf Leaf)) (node 10 Leaf Leaf))"

lemma dell_correct1: "invar t \<Longrightarrow> \<alpha> (dell a t) = {x\<in>\<alpha> t. x\<ge>a}"
  apply(induction t)
  apply(auto)
  done

lemma dell_correct2: "invar t \<Longrightarrow> invar (dell a t)"
  apply(induction t)
  apply(auto simp add: dell_correct1)
  done

(* Homework 2.2 *)

type_synonym vname = string
type_synonym state = "string \<Rightarrow> int"
type_synonym val = "int"

declare algebra_simps[simp]

datatype aexp = N int | V vname | Plus aexp aexp | Mult int aexp

fun aval :: "aexp \<Rightarrow> state \<Rightarrow> val" where
"aval (N n) s = n" |
"aval (V x) s = s x" |
"aval (Plus a1 a2) s = aval a1 s + aval a2 s" |
"aval (Mult i a) s = i * aval a s"

fun normal :: "aexp \<Rightarrow> bool" where
  "normal (N n) = True"
| "normal (V x) = True"
| "normal (Mult i a) = (
    case a of
      (N n) \<Rightarrow> False |
      (V x) \<Rightarrow> True |
      (Mult i a) \<Rightarrow> False |
      (Plus a1 a2) \<Rightarrow> False)"
| "normal (Plus a1 a2) = (normal a1 \<and> normal a2)"

value "normal (Plus (N 6) (Mult 4 (V x)))"
value "normal (Plus (N 6) (Mult 4 (Mult 3 (V y))))"

fun normalize :: "aexp \<Rightarrow> aexp" where
  "normalize (N n) = (N n)"
| "normalize (V x) = (V x)"
| "normalize (Plus a1 a2) = (Plus (normalize a1) (normalize a2))"
| "normalize (Mult i a) = (
    case a of
      (N n) \<Rightarrow> (N (i*n)) |
      (V x) \<Rightarrow> (Mult i (V x)) |
      (Mult x y) \<Rightarrow> normalize (Mult (i*x) y) |
      (Plus x y) \<Rightarrow> (Plus (normalize (Mult i x)) (normalize (Mult i y)))
)"

value "normalize (Plus (N 6) (Mult 4 (Mult 3 (V y))))"
value "normalize (Mult 2 (Plus (V x) (N 21)))"

lemma aux: "aval (normalize a) s = aval a s"
  apply(induction a rule: normalize.induct)
  apply(auto split: aexp.split)
  done

lemma "normal (normalize a)"
  apply(induction a rule: normalize.induct)
  apply(auto simp add: aux split: aexp.split)
  done

end