theory BPlusTree_Set imports
BPlusTree_Split "HOL-Data_Structures.Set_Specs" begin
section"Set interpretation"
(* obsolete fact *) lemma insert_list_length[simp]: assumes"sorted_less ks" and"set (insert_list k ks) = set ks ∪ {k}" and"sorted_less ks ==> sorted_less (insert_list k ks)" shows"length (insert_list k ks) = length ks + (if k ∈ set ks then 0 else 1)" proof - have"distinct (insert_list k ks)" using assms(1) assms(3) strict_sorted_iff by blast thenhave"length (insert_list k ks) = card (set (insert_list k ks))" by (simp add: distinct_card) alsohave"… = card (set ks ∪ {k})" using assms(2) by presburger alsohave"… = card (set ks) + (if k ∈ set ks then 0 else 1)" by (cases "k ∈ set ks") (auto simp add: insert_absorb) alsohave"… = length ks + (if k ∈ set ks then 0 else 1)" using assms(1) distinct_card strict_sorted_iff by auto finallyshow ?thesis. qed
lemma delete_list_length[simp]: assumes"sorted_less ks" and"set (delete_list k ks) = set ks - {k}" and"sorted_less ks ==> sorted_less (delete_list k ks)" shows"length (delete_list k ks) = length ks - (if k ∈ set ks then 1 else 0)" proof - have"distinct (delete_list k ks)" using assms(1) assms(3) strict_sorted_iff by blast thenhave"length (delete_list k ks) = card (set (delete_list k ks))" by (simp add: distinct_card) alsohave"… = card (set ks - {k})" using assms(2) by presburger alsohave"… = card (set ks) - (if k ∈ set ks then 1 else 0)" by (cases "k ∈ set ks") (auto) alsohave"… = length ks - (if k ∈ set ks then 1 else 0)" by (metis assms(1) distinct_card strict_sorted_iff) finallyshow ?thesis. qed
lemma ins_list_length[simp]: assumes"sorted_less ks" shows"length (ins_list k ks) = length ks + (if k ∈ set ks then 0 else 1)" using insert_list_length[of ks ins_list k] by (simp add: assms set_ins_list sorted_ins_list)
lemma del_list_length[simp]: assumes"sorted_less ks" shows"length (del_list k ks) = length ks - (if k ∈ set ks then 1 else 0)" using delete_list_length[of ks ins_list k] by (simp add: assms set_del_list sorted_del_list)
(* TODO what if we define a function "list_split" that returns asplitlistformappingarbitraryf(separators)andg(subtrees) s.th.f::'a\<Rightarrow>('b::linorder)andg::'a\<Rightarrow>'abplustree
this would allow for key,pointer pairs to be inserted into the tree *) (* TODO what if the keys are the pointers? *) locale split_set = split_tree: split_tree split for split:: "('a bplustree × 'a::{linorder,order_top}) list ==> 'a ==> ('a bplustree × 'a) list × ('a bplustree × 'a) list" + fixes isin_list :: "'a ==> ('a::{linorder,order_top}) list ==> bool" and insert_list :: "'a ==> ('a::{linorder,order_top}) list ==> 'a list" and delete_list :: "'a ==> ('a::{linorder,order_top}) list ==> 'a list" assumes insert_list_req: (* TODO locale that derives such a function from a split function similar to the above *) "sorted_less ks ==> isin_list x ks = (x ∈ set ks)" "sorted_less ks ==> insert_list x ks = ins_list x ks" "sorted_less ks ==> delete_list x ks = del_list x ks" begin
lemma insert_list_length[simp]: assumes"sorted_less ks" shows"length (insert_list k ks) = length ks + (if k ∈ set ks then 0 else 1)" using insert_list_req by (simp add: assms)
lemma set_insert_list[simp]: "sorted_less ks ==> set (insert_list k ks) = set ks ∪ {k}" by (simp add: insert_list_req set_ins_list)
lemma sorted_insert_list[simp]: "sorted_less ks ==> sorted_less (insert_list k ks)" by (simp add: insert_list_req sorted_ins_list)
lemma delete_list_length[simp]: assumes"sorted_less ks" shows"length (delete_list k ks) = length ks - (if k ∈ set ks then 1 else 0)" using insert_list_req by (simp add: assms)
lemma set_delete_list[simp]: "sorted_less ks ==> set (delete_list k ks) = set ks - {k}" by (simp add: insert_list_req set_del_list)
lemma sorted_delete_list[simp]: "sorted_less ks ==> sorted_less (delete_list k ks)" by (simp add: insert_list_req sorted_del_list)
definition"empty_bplustree = (Leaf [])"
subsection"Membership"
fun isin:: "'a bplustree ==> 'a ==> bool"where "isin (Leaf ks) x = (isin_list x ks)" | "isin (Node ts t) x = ( case split ts x of (_,(sub,sep)#rs) ==> ( isin sub x ) | (_,[]) ==> isin t x )"
text"Isin proof"
thm isin_simps (* copied from comment in List_Ins_Del *) lemma sorted_ConsD: "sorted_less (y # xs) ==> x ≤ y ==> x ∉ set xs" by (auto simp: sorted_Cons_iff)
lemma sorted_snocD: "sorted_less (xs @ [y]) ==> y ≤ x ==> x ∉ set xs" by (auto simp: sorted_snoc_iff)
lemma isin_sorted: "sorted_less (xs@a#ys) ==> (x ∈ set (xs@a#ys)) = (if x < a then x ∈ set xs else x ∈ set (a#ys))" by (auto simp: isin_simps2)
(* lift to split *)
lemma isin_sorted_split: assumes"Laligned (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, rs)" shows"x ∈ set (leaves (Node ts t)) = (x ∈ set (leaves_list rs @ leaves t))" proof (cases ls) case Nil thenhave"ts = rs" using assms by (auto dest!: split_conc) thenshow ?thesis by simp next case Cons thenobtain ls' sub sep where ls_tail_split: "ls = ls' @ [(sub,sep)]" by (metis list.simps(3) rev_exhaust surj_pair) thenhave x_sm_sep: "sep < x" using split_req(2)[of ts x ls' sub sep rs] using Laligned_sorted_separators[OF assms(1)] using assms sorted_cons sorted_snoc by blast moreoverhave leaves_split: "leaves (Node ts t) = leaves_list ls @ leaves_list rs @ leaves t" using assms(3) split_tree.leaves_split by blast thenshow ?thesis proof (cases "leaves_list ls") case Nil thenshow ?thesis using leaves_split by auto next case Cons thenobtain leavesls' l' where leaves_tail_split: "leaves_list ls = leavesls' @ [l']" by (metis list.simps(3) rev_exhaust) thenhave"l' ≤ sep" proof - have"l' ∈ set (leaves_list ls)" using leaves_tail_split by force thenhave"l' ∈ set (leaves (Node ls' sub))" using ls_tail_split by auto moreoverhave"Laligned (Node ls' sub) sep" using assms split_conc[OF assms(3)] Cons ls_tail_split using Laligned_split_left[of ls' sub sep rs t u] by simp ultimatelyshow ?thesis using Laligned_leaves_inbetween[of "Node ls' sub" sep] by blast qed thenshow ?thesis using assms(2) ls_tail_split leaves_tail_split leaves_split x_sm_sep using isin_sorted[of "leavesls'" l' "leaves_list rs @ leaves t" x] by auto qed qed
lemma isin_sorted_split_right: assumes"split ts x = (ls, (sub,sep)#rs)" and"sorted_less (leaves (Node ts t))" and"Laligned (Node ts t) u" shows"x ∈ set (leaves_list ((sub,sep)#rs) @ leaves t) = (x ∈ set (leaves sub))" proof - from assms have"x ≤ sep" proof - from assms have"sorted_less (separators ts)" by (meson Laligned_sorted_inorder sorted_cons sorted_inorder_separators sorted_snoc) thenshow ?thesis using split_req(3) using assms by fastforce qed moreoverhave leaves_split: "leaves (Node ts t) = leaves_list ls @ leaves sub @ leaves_list rs @ leaves t" using split_conc[OF assms(1)] by auto ultimatelyshow ?thesis proof (cases "leaves_list rs @ leaves t") case Nil thenshow ?thesis using leaves_split by auto next case (Cons r' rs') thenhave"sep < r'" by (metis Laligned_split_right aligned_leaves_inbetween assms(1) assms(3) leaves.simps(2) list.set_intros(1) split_set.split_conc split_set_axioms) thenhave"x < r'" using‹x ≤ sep›by auto moreoverhave"sorted_less (leaves_list ((sub,sep)#rs) @ leaves t)" using assms sorted_wrt_append split_conc by fastforce ultimatelyshow ?thesis using isin_sorted[of "leaves sub""r'""rs'" x] Cons by auto qed qed
theorem isin_set_inorder: assumes"sorted_less (leaves t)" and"aligned l t u" shows"isin t x = (x ∈ set (leaves t))" using assms proof(induction t x arbitrary: l u rule: isin.induct) case (2 ts t x) thenobtain ls rs where list_split: "split ts x = (ls, rs)" by (meson surj_pair) thenhave list_conc: "ts = ls @ rs" using split_conc by auto show ?case proof (cases rs) case Nil thenhave"isin (Node ts t) x = isin t x" by (simp add: list_split) alsohave"… = (x ∈ set (leaves t))" using"2.IH"(1)[of ls rs] list_split Nil using"2.prems" sorted_leaves_induct_last align_last' by metis alsohave"… = (x ∈ set (leaves (Node ts t)))" using isin_sorted_split using"2.prems" list_split list_conc Nil by (metis aligned_imp_Laligned leaves.simps(2) leaves_conc same_append_eq self_append_conv) finallyshow ?thesis . next case (Cons a list) thenobtain sub sep where a_split: "a = (sub,sep)" by (cases a) thenhave"isin (Node ts t) x = isin sub x" using list_split Cons a_split by auto alsohave"… = (x ∈ set (leaves sub))" using"2.IH"(2)[of ls rs "(sub,sep)" list sub sep] using"2.prems" a_split list_conc list_split local.Cons sorted_leaves_induct_subtree
align_sub by (metis in_set_conv_decomp) alsohave"… = (x ∈ set (leaves (Node ts t)))" using isin_sorted_split using isin_sorted_split_right "2.prems" list_split Cons a_split using aligned_imp_Laligned by blast finallyshow ?thesis . qed qed (auto simp add: insert_list_req)
theorem isin_set_Linorder: assumes"sorted_less (leaves t)" and"Laligned t u" shows"isin t x = (x ∈ set (leaves t))" using assms proof(induction t x arbitrary: u rule: isin.induct) case (2 ts t x) thenobtain ls rs where list_split: "split ts x = (ls, rs)" by (meson surj_pair) thenhave list_conc: "ts = ls @ rs" using split_conc by auto show ?case proof (cases rs) case Nil thenhave"isin (Node ts t) x = isin t x" by (simp add: list_split) alsohave"… = (x ∈ set (leaves t))" by (metis "2.IH"(1) "2.prems"(1) "2.prems"(2) Lalign_Llast list_split local.Nil sorted_leaves_induct_last) alsohave"… = (x ∈ set (leaves (Node ts t)))" using isin_sorted_split using"2.prems" list_split list_conc Nil by simp finallyshow ?thesis . next case (Cons a list) thenobtain sub sep where a_split: "a = (sub,sep)" by (cases a) thenhave"isin (Node ts t) x = isin sub x" using list_split Cons a_split by auto alsohave"… = (x ∈ set (leaves sub))" using"2.IH"(2)[of ls rs "(sub,sep)" list sub sep] using"2.prems" a_split list_conc list_split local.Cons sorted_leaves_induct_subtree
align_sub by (metis Lalign_Llast Laligned_split_left) alsohave"… = (x ∈ set (leaves (Node ts t)))" using isin_sorted_split using isin_sorted_split_right "2.prems" list_split Cons a_split by simp finallyshow ?thesis . qed qed (auto simp add: insert_list_req)
corollary isin_set_Linorder_top: assumes"sorted_less (leaves t)" and"Laligned t top" shows"isin t x = (x ∈ set (leaves t))" using assms isin_set_Linorder by simp
subsection"Insertion"
text"The insert function requires an auxiliary data structure and auxiliary invariant functions."
fun order_upiwhere "order_upi k (Ti sub) = order k sub" | "order_upi k (Upi l a r) = (order k l ∧ order k r)"
fun root_order_upiwhere "root_order_upi k (Ti sub) = root_order k sub" | "root_order_upi k (Upi l a r) = (order k l ∧ order k r)"
fun height_upiwhere "height_upi (Ti t) = height t" | "height_upi (Upi l a r) = max (height l) (height r)"
fun bal_upiwhere "bal_upi (Ti t) = bal t" | "bal_upi (Upi l a r) = (height l = height r ∧ bal l ∧ bal r)"
fun inorder_upiwhere "inorder_upi (Ti t) = inorder t" | "inorder_upi (Upi l a r) = inorder l @ [a] @ inorder r"
fun leaves_upiwhere "leaves_upi (Ti t) = leaves t" | "leaves_upi (Upi l a r) = leaves l @ leaves r"
fun aligned_upiwhere "aligned_upi l (Ti t) u = aligned l t u" | "aligned_upi l (Upi lt a rt) u = (aligned l lt a ∧ aligned a rt u)"
fun Laligned_upiwhere "Laligned_upi (Ti t) u = Laligned t u" | "Laligned_upi (Upi lt a rt) u = (Laligned lt a ∧ aligned a rt u)"
text"The following function merges two nodes and returns separately split nodes if an overflow occurs"
(* note here that splitting away the last element is actually very nice
from the implementation perspective *) fun nodei:: "nat ==> ('a bplustree × 'a) list ==> 'a bplustree ==> 'a upi"where "nodei k ts t = ( if length ts ≤ 2*k then Ti (Node ts t) else ( case split_half ts of (ls, rs) ==> case last ls of (sub,sep) ==> Upi (Node (butlast ls) sub) sep (Node rs t) ) )"
fun Lnodei:: "nat ==> 'a list ==> 'a upi"where "Lnodei k ts = ( if length ts ≤ 2*k then Ti (Leaf ts) else ( case split_half ts of (ls, rs) ==> Upi (Leaf ls) (last ls) (Leaf rs) ) )"
fun ins:: "nat ==> 'a ==> 'a bplustree ==> 'a upi"where "ins k x (Leaf ks) = Lnodei k (insert_list x ks)" | "ins k x (Node ts t) = ( case split ts x of (ls,(sub,sep)#rs) ==> (case ins k x sub of Upi l a r ==> nodei k (ls@(l,a)#(r,sep)#rs) t | Ti a ==> Ti (Node (ls@(a,sep)#rs) t)) | (ls, []) ==> (case ins k x t of Upi l a r ==> nodei k (ls@[(l,a)]) r | Ti a ==> Ti (Node ls a) ) )"
fun treei::"'a upi==> 'a bplustree"where "treei (Ti sub) = sub" | "treei (Upi l a r) = (Node [(l,a)] r)"
fun insert::"nat ==> 'a ==> 'a bplustree ==> 'a bplustree"where "insert k x t = treei (ins k x t)"
subsection"Proofs of functional correctness"
lemma nodei_ti_simp: "nodei k ts t = Ti x ==> x = Node ts t" apply (cases "length ts ≤ 2*k") apply (auto split!: list.splits prod.splits) done
lemma Lnodei_ti_simp: "Lnodei k ts = Ti x ==> x = Leaf ts" apply (cases "length ts ≤ 2*k") apply (auto split!: list.splits) done
lemma split_set: assumes"split ts z = (ls,(a,b)#rs)" shows"(a,b) ∈ set ts" and"(x,y) ∈ set ls ==> (x,y) ∈ set ts" and"(x,y) ∈ set rs ==> (x,y) ∈ set ts" and"set ls ∪ set rs ∪ {(a,b)} = set ts" and"∃x ∈ set ts. b ∈ Basic_BNFs.snds x" using split_conc assms by fastforce+
lemma split_length: "split ts x = (ls, rs) ==> length ls + length rs = length ts" by (auto dest: split_conc)
(* TODO way to use this for custom case distinction? *) lemma nodei_cases: "length xs ≤ k ∨ (∃ls sub sep rs. split_half xs = (ls@[(sub,sep)],rs))" proof - have"¬ length xs ≤ k ==> length xs ≥ 1" by linarith thenshow ?thesis using split_half_not_empty by fastforce qed
lemma Lnodei_cases: "length xs ≤ k ∨ (∃ls sep rs. split_half xs = (ls@[sep],rs))" proof - have"¬ length xs ≤ k ==> length xs ≥ 1" by linarith thenshow ?thesis using split_half_not_empty by fastforce qed
lemma root_order_treei: "root_order_upi (Suc k) t = root_order (Suc k) (treei t)" apply (cases t) apply auto done
lemma length_take_left: "length (take ((length ts + 1) div 2) ts) = (length ts + 1) div 2" apply (cases ts) apply auto done
lemma nodei_root_order: assumes"length ts > 0" and"length ts ≤ 4*k+1" and"∀x ∈ set (subtrees ts). order k x" and"order k t" shows"root_order_upi k (nodei k ts t)" proof (cases "length ts ≤ 2*k") case True thenshow ?thesis using assms by (simp add: nodei.simps) next case False thenobtain ls sub sep rs where split_half_ts: "take ((length ts + 1) div 2) ts = ls@[(sub,sep)]" using split_half_not_empty[of ts] by auto thenhave length_ls: "length ls = (length ts + 1) div 2 - 1" by (metis One_nat_def add_diff_cancel_right' add_self_div_2 bits_1_div_2 length_append length_take_left list.size(3) list.size(4) odd_one odd_succ_div_two) alsohave"…≤ (4*k + 1) div 2" using assms(2) by simp alsohave"… = 2*k" by auto finallyhave"length ls ≤ 2*k" by simp moreoverhave"length ls ≥ k" using False length_ls by simp moreoverhave"set (ls@[(sub,sep)]) ⊆ set ts" by (metis split_half_ts(1) set_take_subset) ultimatelyhave o_r: "order k (Node ls sub)" using split_half_ts assms by auto have "butlast (take ((length ts + 1) div 2) ts) = ls" "last (take ((length ts + 1) div 2) ts) = (sub,sep)" using split_half_ts by auto thenshow ?thesis using o_r assms set_drop_subset[of _ ts] by (auto simp add: False split_half_ts split!: prod.splits) qed
lemma nodei_order_helper: assumes"length ts ≥ k" and"length ts ≤ 4*k+1" and"∀x ∈ set (subtrees ts). order k x" and"order k t" shows"case (nodei k ts t) of Ti t ==> order k t | _ ==> True" proof (cases "length ts ≤ 2*k") case True thenshow ?thesis using assms by (simp add: nodei.simps) next case False thenobtain sub sep ls where "take ((length ts + 1) div 2) ts = ls@[(sub,sep)]" using split_half_not_empty[of ts] by fastforce thenshow ?thesis using assms by simp qed
lemma nodei_order: assumes"length ts ≥ k" and"length ts ≤ 4*k+1" and"∀x ∈ set (subtrees ts). order k x" and"order k t" shows"order_upi k (nodei k ts t)" apply(cases "nodei k ts t") using nodei_root_order nodei_order_helper assms apply fastforce by (metis (full_types) assms le_0_eq nat_le_linear nodei.elims nodei_root_order order_upi.simps(2) root_order_upi.simps(2) upi.simps(4) verit_comp_simplify1(3))
lemma Lnodei_root_order: assumes"length ts > 0" and"length ts ≤ 4*k" shows"root_order_upi k (Lnodei k ts)" proof (cases "length ts ≤ 2*k") case True thenshow ?thesis using assms by simp next case False thenobtain ls sep rs where split_half_ts: "take ((length ts + 1) div 2) ts = ls@[sep]" "drop ((length ts + 1) div 2) ts = rs" using split_half_not_empty[of ts] by auto thenhave length_ls: "length ls = ((length ts + 1) div 2) - 1" by (metis One_nat_def add_diff_cancel_right' add_self_div_2 bits_1_div_2 length_append length_take_left list.size(3) list.size(4) odd_one odd_succ_div_two) alsohave"… < (4*k + 1) div 2" using assms(2) by (smt (z3) Groups.add_ac(2) One_nat_def split_half_ts add.right_neutral diff_is_0_eq' div_le_mono le_add_diff_inverse le_neq_implies_less length_append length_take_left less_add_Suc1 less_imp_diff_less list.size(4) nat_le_linear not_less_eq plus_nat.simps(2)) alsohave"… = 2*k" by auto finallyhave"length ls < 2*k" by simp moreoverhave"length ls ≥ k" using False length_ls by simp ultimatelyhave o_l: "order k (Leaf (ls@[sep]))" using set_take_subset assms split_half_ts by fastforce thenshow ?thesis using assms split_half_ts False by auto qed
lemma Lnodei_order_helper: assumes"length ts ≥ k" and"length ts ≤ 4*k+1" shows"case (Lnodei k ts) of Ti t ==> order k t | _ ==> True" proof (cases "length ts ≤ 2*k") case True thenshow ?thesis using assms by (simp add: nodei.simps) next case False thenobtain sep ls where "take ((length ts + 1) div 2) ts = ls@[sep]" using split_half_not_empty[of ts] by fastforce thenshow ?thesis using assms by simp qed
(* explicit proof *) lemma ins_order: "k > 0 ==> sorted_less (leaves t) ==> order k t ==> order_upi k (ins k x t)" proof(induction k x t rule: ins.induct) case (1 k x ts) thenshow ?case by auto (* this proof requires both sorted_less and k > 0 *) next case (2 k x ts t) thenobtain ls rs where split_res: "split ts x = (ls, rs)" by (meson surj_pair) thenhave split_app: "ts = ls@rs" using split_conc by simp
show ?case proof (cases rs) case Nil thenhave"order_upi k (ins k x t)" using2 split_res sorted_leaves_induct_last by auto thenshow ?thesis using Nil 2 split_app split_res Nil nodei_order by (auto split!: upi.splits simp del: nodei.simps) next case (Cons a list) thenobtain sub sep where a_prod: "a = (sub, sep)" by (cases a) thenhave"sorted_less (leaves sub)" using"2"(4) Cons sorted_leaves_induct_subtree split_app by blast thenhave"order_upi k (ins k x sub)" using"2.IH"(2) "2.prems" a_prod local.Cons split_app split_res by auto thenshow ?thesis using2 split_app Cons length_append nodei_order[of k "ls@_#_#list"] a_prod split_res by (auto split!: upi.splits simp del: nodei.simps simp add: order_impl_root_order) qed qed
(* notice this is almost a duplicate of ins_order *) lemma ins_root_order: assumes"k > 0""sorted_less (leaves t)""root_order k t" shows"root_order_upi k (ins k x t)" proof(cases t) case (Leaf ks) thenshow ?thesis using assms by (auto simp add: Lnodei_order min_absorb2) (* this proof requires both sorted_less and k > 0 *) next case (Node ts t) thenobtain ls rs where split_res: "split ts x = (ls, rs)" by (meson surj_pair) thenhave split_app: "ls@rs = ts" using split_conc by fastforce
show ?thesis proof (cases rs) case Nil thenhave"order_upi k (ins k x t)" using Node assms split_res sorted_leaves_induct_last using ins_order[of k t] by auto thenshow ?thesis using Nil Node split_app split_res assms nodei_root_order by (auto split!: upi.splits simp del: nodei.simps simp add: order_impl_root_order) next case (Cons a list) thenobtain sub sep where a_prod: "a = (sub, sep)" by (cases a) thenhave"sorted_less (leaves sub)" using Node assms(2) local.Cons sorted_leaves_induct_subtree split_app by blast thenhave"order_upi k (ins k x sub)" using Node a_prod assms ins_order local.Cons split_app by auto thenshow ?thesis using assms split_app Cons length_append Node nodei_root_order a_prod split_res by (auto split!: upi.splits simp del: nodei.simps simp add: order_impl_root_order) qed qed
lemma height_list_split: "height_upi (Upi (Node ls a) b (Node rs t)) = height (Node (ls@(a,b)#rs) t) " by (induction ls) (auto simp add: max.commute)
lemma nodei_height: "height_upi (nodei k ts t) = height (Node ts t)" proof(cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half ts = (ls@[(sub,sep)], rs)" by (meson nodei_cases) thenhave"nodei k ts t = Upi (Node ls (sub)) sep (Node rs t)" using False by simp thenhave"height_upi (nodei k ts t) = height (Node (ls@(sub,sep)#rs) t)" by (metis height_list_split) alsohave"… = height (Node ts t)" by (metis (no_types, lifting) Pair_inject append_Cons append_eq_append_conv2 append_take_drop_id self_append_conv split_half.simps split_half_ts) finallyshow ?thesis. qed simp
lemma Lnodei_height: "height_upi (Lnodei k xs) = height (Leaf xs)" by (auto)
lemma bal_upi_tree: "bal_upi t = bal (treei t)" apply(cases t) apply auto done
lemma bal_list_split: "bal (Node (ls@(a,b)#rs) t) ==> bal_upi (Upi (Node ls a) b (Node rs t))" by (auto simp add: image_constant_conv)
lemma nodei_bal: assumes"bal (Node ts t)" shows"bal_upi (nodei k ts t)" using assms proof(cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half ts = (ls@[(sub,sep)], rs)" by (meson nodei_cases) thenhave"bal (Node (ls@(sub,sep)#rs) t)" using assms append_take_drop_id[where n="(length ts + 1) div 2"and xs=ts] by auto thenshow ?thesis using split_half_ts assms False by (auto simp del: bal.simps bal_upi.simps dest!: bal_list_split[of ls sub sep rs t]) qed simp
lemma nodei_aligned: assumes"aligned l (Node ts t) u" shows"aligned_upi l (nodei k ts t) u" using assms proof (cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half ts = (ls@[(sub,sep)], rs)" by (meson nodei_cases) thenhave"aligned l (Node ls sub) sep" by (metis aligned_split_left append.assoc append_Cons append_take_drop_id assms prod.sel(1) split_half.simps) moreoverhave"aligned sep (Node rs t) u" by (smt (z3) Pair_inject aligned_split_right append.assoc append_Cons append_Nil2 append_take_drop_id assms same_append_eq split_half.simps split_half_ts) ultimatelyshow ?thesis using split_half_ts False by auto qed simp
lemma nodei_Laligned: assumes"Laligned (Node ts t) u" shows"Laligned_upi (nodei k ts t) u" using assms proof (cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half ts = (ls@[(sub,sep)], rs)" by (meson nodei_cases) thenhave"Laligned (Node ls sub) sep" by (metis Laligned_split_left append.assoc append_Cons assms split_half_conc) moreoverhave"aligned sep (Node rs t) u" by (metis Laligned_split_right append.assoc append_Cons append_Nil2 assms same_append_eq split_half_conc split_half_ts) ultimatelyshow ?thesis using split_half_ts False by auto qed simp
lemma length_right_side: "length xs > 1 ==> length (drop ((length xs + 1) div 2) xs) > 0" by auto
lemma Lnodei_aligned: assumes"aligned l (Leaf ks) u" and"sorted_less ks" and"k > 0" shows"aligned_upi l (Lnodei k ks) u" using assms proof (cases "length ks ≤ 2*k") case False thenobtain ls sep rs where split_half_ts: "take ((length ks + 1) div 2) ks = ls@[sep]" "drop ((length ks + 1) div 2) ks = rs" using split_half_not_empty[of ks] by auto moreoverhave"sorted_less (ls@[sep])" by (metis append_take_drop_id assms(2) sorted_wrt_append split_half_ts(1)) ultimatelyhave"aligned l (Leaf (ls@[sep])) sep" using split_half_conc[of ks "ls@[sep]" rs] assms sorted_snoc_iff[of ls sep] by auto moreoverhave"aligned sep (Leaf rs) u" proof - have"length rs > 0" using False assms(3) split_half_ts(2) by fastforce thenobtain sep' rs' where"rs = sep' # rs'" by (cases rs) auto moreoverhave"sep < sep'" by (metis append_take_drop_id assms(2) calculation in_set_conv_decomp sorted_mid_iff sorted_snoc_iff split_half_ts(1) split_half_ts(2)) moreoverhave"sorted_less rs" by (metis append_take_drop_id assms(2) sorted_wrt_append split_half_ts(2)) ultimatelyshow ?thesis using split_half_ts split_half_conc[of ks "ls@[sep]" rs] assms by auto qed ultimatelyshow ?thesis using split_half_ts False by auto qed simp
lemma height_upi_merge: "height_upi (Upi l a r) = height t ==> height (Node (ls@(t,x)#rs) tt) = height (Node (ls@(l,a)#(r,x)#rs) tt)" by simp
lemma ins_height: "height_upi (ins k x t) = height t" proof(induction k x t rule: ins.induct) case (2 k x ts t) thenobtain ls rs where split_list: "split ts x = (ls,rs)" by (meson surj_pair) thenhave split_append: "ts = ls@rs" using split_conc by auto thenshow ?case proof (cases rs) case Nil thenhave height_sub: "height_upi (ins k x t) = height t" using2by (simp add: split_list) thenshow ?thesis proof (cases "ins k x t") case (Ti a) thenhave"height (Node ts t) = height (Node ts a)" using height_sub by simp thenshow ?thesis using Ti Nil split_list split_append by simp next case (Upi l a r) thenhave"height (Node ls t) = height (Node (ls@[(l,a)]) r)" using height_bplustree_order height_sub by (induction ls) auto thenshow ?thesis using2 Nil split_list Upi split_append by (simp del: nodei.simps add: nodei_height) qed next case (Cons a list) thenobtain sub sep where a_split: "a = (sub,sep)" by (cases a) auto thenhave height_sub: "height_upi (ins k x sub) = height sub" by (metis "2.IH"(2) a_split Cons split_list) thenshow ?thesis proof (cases "ins k x sub") case (Ti a) thenhave"height a = height sub" using height_sub by auto thenhave"height (Node (ls@(sub,sep)#rs) t) = height (Node (ls@(a,sep)#rs) t)" by auto thenshow ?thesis using Ti height_sub Cons 2 split_list a_split split_append by (auto simp add: image_Un max.commute finite_set_ins_swap) next case (Upi l a r) thenhave"height (Node (ls@(sub,sep)#list) t) = height (Node (ls@(l,a)#(r,sep)#list) t)" using height_upi_merge height_sub by fastforce thenshow ?thesis using Upi Cons 2 split_list a_split split_append by (auto simp del: nodei.simps simp add: nodei_height image_Un max.commute finite_set_ins_swap) qed qed qed simp
(* the below proof is overly complicated as a number of lemmas regarding height are missing *) lemma ins_bal: "bal t ==> bal_upi (ins k x t)" proof(induction k x t rule: ins.induct) case (2 k x ts t) thenobtain ls rs where split_res: "split ts x = (ls, rs)" by (meson surj_pair) thenhave split_app: "ts = ls@rs" using split_conc by fastforce
show ?case proof (cases rs) case Nil thenshow ?thesis proof (cases "ins k x t") case (Ti a) thenhave"bal (Node ls a)"unfolding bal.simps by (metis "2.IH"(1) "2.prems" append_Nil2 bal.simps(2) bal_upi.simps(1) height_upi.simps(1) ins_height local.Nil split_app split_res) thenshow ?thesis using Nil Ti2 split_res by simp next case (Upi l a r) thenhave "(∀x∈set (subtrees (ls@[(l,a)])). bal x)" "(∀x∈set (subtrees ls). height r = height x)" using2 Upi Nil split_res split_app by simp_all (metis height_upi.simps(2) ins_height max_def) thenshow ?thesis unfolding ins.simps using Upi Nil 2 split_res by (simp del: nodei.simps add: nodei_bal) qed next case (Cons a list) thenobtain sub sep where a_prod: "a = (sub, sep)"by (cases a) thenhave"bal_upi (ins k x sub)"using2 split_res using a_prod local.Cons split_app by auto show ?thesis proof (cases "ins k x sub") case (Ti x1) thenhave"height x1 = height t" by (metis "2.prems" a_prod add_diff_cancel_left' bal_split_left(1) bal_split_left(2) height_bal_tree height_upi.simps(1) ins_height local.Cons plus_1_eq_Suc split_app) thenshow ?thesis using split_app Cons Ti2 split_res a_prod by auto next case (Upi l a r) (* The only case where explicit reasoning is required - likely due to the insertion of 2 elements in the list *) thenhave "∀x ∈ set (subtrees (ls@(l,a)#(r,sep)#list)). bal x" using Upi split_app Cons 2‹bal_upi (ins k x sub)›by auto moreoverhave"∀x ∈ set (subtrees (ls@(l,a)#(r,sep)#list)). height x = height t" using Upi split_app Cons 2‹bal_upi (ins k x sub)› ins_height split_res a_prod apply auto by (metis height_upi.simps(2) sup.idem sup_nat_def) ultimatelyshow ?thesis using Upi Cons 2 split_res a_prod by (simp del: nodei.simps add: nodei_bal) qed qed qed simp
(* ins acts as ins_list wrt inorder *)
(* "simple enough" to be automatically solved *) lemma nodei_leaves: "leaves_upi (nodei k ts t) = leaves (Node ts t)" proof (cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half ts = (ls@[(sub,sep)], rs)" by (meson nodei_cases) thenhave"leaves_upi (nodei k ts t) = leaves_list ls @ leaves sub @ leaves_list rs @ leaves t" using False by auto alsohave"… = leaves (Node ts t)" using split_half_ts split_half_conc[of ts "ls@[(sub,sep)]" rs] by auto finallyshow ?thesis. qed simp
corollary nodei_leaves_simps: "nodei k ts t = Ti t' ==> leaves t' = leaves (Node ts t)" "nodei k ts t = Upi l a r ==> leaves l @ leaves r = leaves (Node ts t)" apply (metis leaves_upi.simps(1) nodei_leaves) by (metis leaves_upi.simps(2) nodei_leaves)
lemma Lnodei_leaves: "leaves_upi (Lnodei k xs) = leaves (Leaf xs)" proof (cases "length xs ≤ 2*k") case False thenobtain ls sub sep rs where
split_half_ts: "split_half xs = (ls@[sep], rs)" by (meson Lnodei_cases) thenhave"leaves_upi (Lnodei k xs) = ls @ sep # rs" using False by auto alsohave"… = leaves (Leaf xs)" using split_half_ts split_half_conc[of xs "ls@[sep]" rs] by auto finallyshow ?thesis. qed simp
corollary Lnodei_leaves_simps: "Lnodei k xs = Ti t ==> leaves t = leaves (Leaf xs)" "Lnodei k xs = Upi l a r ==> leaves l @ leaves r = leaves (Leaf xs)" apply (metis leaves_upi.simps(1) Lnodei_leaves) by (metis leaves_upi.simps(2) Lnodei_leaves)
(* specialize ins_list_sorted since it is cumbersome to express
"inorder_list ts" as "xs @ [a]" and always having to use the implicit properties of split*)
lemma ins_list_split: assumes"Laligned (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, rs)" shows"ins_list x (leaves (Node ts t)) = leaves_list ls @ ins_list x (leaves_list rs @ leaves t)" proof (cases ls) case Nil thenshow ?thesis using assms by (auto dest!: split_conc) next case Cons thenobtain ls' sub sep where ls_tail_split: "ls = ls' @ [(sub,sep)]" by (metis list.distinct(1) rev_exhaust surj_pair) have sorted_inorder: "sorted_less (inorder (Node ts t))" using Laligned_sorted_inorder assms(1) sorted_cons sorted_snoc by blast moreoverhave x_sm_sep: "sep < x" using split_req(2)[of ts x ls' sub sep rs] using sorted_inorder_separators[of ts t] sorted_inorder using assms ls_tail_split by auto moreoverhave leaves_split: "leaves (Node ts t) = leaves_list ls @ leaves_list rs @ leaves t" using assms(3) split_tree.leaves_split by blast thenshow ?thesis proof (cases "leaves_list ls") case Nil thenshow ?thesis by (metis append_self_conv2 leaves_split) next case Cons thenobtain leavesls' l' where leaves_tail_split: "leaves_list ls = leavesls' @ [l']" by (metis list.simps(3) rev_exhaust) thenhave"l' ≤ sep" proof - have"l' ∈ set (leaves_list ls)" using leaves_tail_split by force thenhave"l' ∈ set (leaves (Node ls' sub))" using ls_tail_split by auto moreoverhave"Laligned (Node ls' sub) sep" using assms split_conc[OF assms(3)] Cons ls_tail_split using Laligned_split_left[of ls' sub sep rs t u] by simp ultimatelyshow ?thesis using Laligned_leaves_inbetween[of "Node ls' sub" sep] by blast qed moreoverhave"sorted_less (leaves_list ls)" using assms(2) leaves_split sorted_wrt_append by auto ultimatelyshow ?thesis using assms(2) ls_tail_split leaves_tail_split leaves_split x_sm_sep using ins_list_sorted[of leavesls' l' x "leaves_list rs@leaves t"] by auto qed qed
lemma ins_list_split_right: assumes"split ts x = (ls, (sub,sep)#rs)" and"sorted_less (leaves (Node ts t))" and"Laligned (Node ts t) u" shows"ins_list x (leaves_list ((sub,sep)#rs) @ leaves t) = ins_list x (leaves sub) @ leaves_list rs @ leaves t" proof - from assms have x_sm_sep: "x ≤ sep" proof - from assms have"sorted_less (separators ts)" using Laligned_sorted_separators sorted_cons sorted_snoc by blast thenshow ?thesis using split_req(3) using assms by blast qed thenshow ?thesis proof (cases "leaves_list rs @ leaves t") case Nil moreoverhave"leaves_list ((sub,sep)#rs) @ leaves t = leaves sub @ leaves_list rs @ leaves t" by simp ultimatelyshow ?thesis by (metis self_append_conv) next case (Cons r' rs') thenhave"sep < r'" by (metis aligned_leaves_inbetween Laligned_split_right assms(1) assms(3) leaves.simps(2) list.set_intros(1) split_set.split_conc split_set_axioms) thenhave"x < r'" using‹x ≤ sep›by auto moreoverhave"sorted_less (leaves sub @ [r'])" proof - have"sorted_less (leaves_list ls @ leaves sub @ leaves_list rs @ leaves t)" using assms(1) assms(2) split_tree.leaves_split split_set_axioms by fastforce thenshow ?thesis using assms by (metis Cons sorted_mid_iff sorted_wrt_append) qed ultimatelyshow ?thesis using ins_list_sorted[of "leaves sub" r' x rs'] Cons by auto qed qed
(* a simple lemma, missing from the standard as of now *) lemma ins_list_idem_eq_isin: "sorted_less xs ==> x ∈ set xs ⟷ (ins_list x xs = xs)" apply(induction xs) apply auto done
lemma ins_list_contains_idem: "[sorted_less xs; x ∈ set xs]==> (ins_list x xs = xs)" using ins_list_idem_eq_isin by auto
lemma aligned_insert_list: "sorted_less ks ==> l < x ==> x ≤ u ==> aligned l (Leaf ks) u ==> aligned l (Leaf (insert_list x ks)) u" using insert_list_req by (simp add: set_ins_list)
lemma align_subst_two: "aligned l (Node (ts@[(sub,sep)]) t) u ==> aligned sep lt a==> aligned a rt u ==> aligned l (Node (ts@[(sub,sep),(lt,a)]) rt) u" apply(induction ts arbitrary: l) apply auto done
lemma align_subst_three: "aligned l (Node (ls@(subl,sepl)#(subr,sepr)#rs) t) u ==> aligned sepl lt a ==> aligned a rt sepr ==> aligned l (Node (ls@(subl,sepl)#(lt,a)#(rt,sepr)#rs) t) u" apply(induction ls arbitrary: l) apply auto done
lemma ins_inorder: assumes"k > 0" and"aligned l t u" and"sorted_less (leaves t)" and"root_order k t" and"l < x""x ≤ u" shows"(leaves_upi (ins k x t)) = ins_list x (leaves t) ∧ aligned_upi l (ins k x t) u" using assms proof(induction k x t arbitrary: l u rule: ins.induct) case (1 k x ks) thenshow ?case proof (safe, goal_cases) case _: 1 thenshow ?case using1 insert_list_req by auto next case2 from1have"aligned l (Leaf (insert_list x ks)) u" by (metis aligned_insert_list leaves.simps(1)) moreoverhave"sorted_less (insert_list x ks)" using"1.prems"(3) split_set.insert_list_req split_set_axioms by auto ultimatelyshow ?case using Lnodei_aligned[of l "insert_list x ks" u k] 1 by (auto simp del: Lnodei.simps split_half.simps) qed next case (2 k x ts t) thenobtain ls rs where list_split: "split ts x = (ls,rs)" by (cases "split ts x") thenhave list_conc: "ts = ls@rs" using split_set.split_conc split_set_axioms by blast thenshow ?case proof (cases rs) case Nil thenobtain ts' sub' sep' where"ts = ts'@[(sub',sep')]" apply(cases ts) using2 list_conc Nil apply(simp) by (metis isin.cases list.distinct(1) rev_exhaust) have IH: "leaves_upi (ins k x t) = ins_list x (leaves t) ∧ aligned_upi sep' (ins k x t) u" proof - (* we need to fulfill all these IH requirements *) note"2.IH"(1)[OF sym[OF list_split] Nil "2.prems"(1), of sep' u] have"sorted_less (leaves t)" using"2.prems"(3) sorted_leaves_induct_last by blast moreoverhave"sep' < x" using split_req[of ts x] list_split by (metis "2.prems"(2) ‹ts = ts' @ [(sub', sep')]› aligned_sorted_separators local.Nil self_append_conv sorted_cons sorted_snoc) moreoverhave"aligned sep' t u" using"2.prems"(2) ‹ts = ts' @ [(sub', sep')]› align_last by blast ultimatelyshow ?thesis using"2.IH"(1)[OF sym[OF list_split] Nil "2.prems"(1), of sep' u] using"2.prems" list_split local.Nil sorted_leaves_induct_last using order_impl_root_order by auto qed show ?thesis proof (cases "ins k x t") case (Ti a) have IH: "leaves a = ins_list x (leaves t) ∧ aligned sep' a u" using IH Tiby force show ?thesis proof(safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a" using list_split Ti Nil by (auto simp add: list_conc) alsohave"… = leaves_list ls @ (ins_list x (leaves t))" by (simp add: IH) alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split using"2.prems" list_split Nil by (metis aligned_imp_Laligned append_self_conv2 concat.simps(1) list.simps(8)) finallyshow ?case . next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned l (Node ts a) u" using Nil Ti list_split list_conc by simp moreoverhave"aligned l (Node ts a) u" using"2.prems"(2) by (metis IH ‹ts = ts' @ [(sub', sep')]› aligned_subst_last) ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves t) ∧ aligned_upi sep' (Upi lt a rt) u" using IH by auto
show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves_upi (Upi lt a rt)" using list_split Upi Nil by (auto simp add: list_conc) alsohave"… = leaves_list ls @ ins_list x (leaves t)" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split using"2.prems" list_split local.Nil by (metis aligned_imp_Laligned append_self_conv2 concat.simps(1) list.simps(8)) finallyshow ?case. next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned_upi l (nodei k (ts @ [(lt, a)]) rt) u" using Nil Upi list_split list_conc nodei_alignedby simp moreoverhave"aligned l (Node (ts@[(lt,a)]) rt) u" using"2.prems"(2) IH ‹ts = ts' @ [(sub', sep')]› align_subst_two by fastforce ultimatelyshow ?case using nodei_aligned by auto qed qed next case (Cons h list) thenobtain sub sep where h_split: "h = (sub,sep)" by (cases h)
thenhave sorted_inorder_sub: "sorted_less (leaves sub)" using"2.prems" list_conc Cons sorted_leaves_induct_subtree by fastforce moreoverhave order_sub: "order k sub" using"2.prems" list_conc Cons h_split by auto thenshow ?thesis (* TODO way to show this cleanly without distinguishing cases for ls? *) proof (cases ls) case Nil thenhave aligned_sub: "aligned l sub sep" using"2.prems"(2) list_conc h_split Cons by auto thenhave IH: "leaves_upi (ins k x sub) = ins_list x (leaves sub) ∧ aligned_upi l (ins k x sub) sep" proof - have"x ≤ sep" using"2.prems"(2) aligned_sorted_separators h_split list_split local.Cons sorted_cons sorted_snoc split_set.split_req(3) split_set_axioms by blast thenshow ?thesis using"2.IH"(2)[OF sym[OF list_split] Cons sym[OF h_split], of l sep] using"2.prems" list_split local.Nil aligned_sub sorted_inorder_sub order_sub using order_impl_root_order by auto qed thenshow ?thesis proof (cases "ins k x sub") case (Ti a) have IH:"leaves a = ins_list x (leaves sub) ∧ aligned l a sep" using Ti IH by (auto) show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a @ leaves_list list @ leaves t" using h_split list_split Ti Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by (metis aligned_imp_Laligned) finallyshow ?case. next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned l (Node ((a,sep)#list) t) u" using Nil Cons list_conc list_split h_split Tiby simp moreoverhave"aligned l (Node ((a,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil by auto ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves sub) ∧ aligned_upi l (Upi lt a rt) sep" using IH h_split list_split Cons sorted_inorder_sub by auto show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves lt @ leaves rt @ leaves_list list @ leaves t" using h_split list_split Upi Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by (metis aligned_imp_Laligned) finallyshow ?case. next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned_upi l (nodei k ((lt,a)#(rt,sep)#list) t) u" using Nil Cons list_conc list_split h_split Upiby simp moreoverhave"aligned l (Node ((lt,a)#(rt,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil by auto ultimatelyshow ?case using nodei_alignedby auto qed qed next case ls_split': Cons thenobtain ls' sub' sep' where ls_split: "ls = ls'@[(sub',sep')]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave aligned_sub: "aligned sep' sub sep" using"2.prems"(2) list_conc h_split Cons using align_last aligned_split_left by blast thenhave IH: "leaves_upi (ins k x sub) = ins_list x (leaves sub) ∧ aligned_upi sep' (ins k x sub) sep" proof - have"x ≤ sep" using"2.prems"(2) aligned_sorted_separators h_split list_split local.Cons sorted_cons sorted_snoc split_set.split_req(3) split_set_axioms by blast moreoverhave"sep' < x" using"2.prems"(2) aligned_sorted_separators list_split ls_split sorted_cons sorted_snoc split_set.split_req(2) split_set_axioms by blast ultimatelyshow ?thesis using"2.IH"(2)[OF sym[OF list_split] Cons sym[OF h_split], of sep' sep] using"2.prems" list_split ls_split aligned_sub sorted_inorder_sub order_sub using order_impl_root_order by auto qed thenshow ?thesis proof (cases "ins k x sub") case (Ti a) have IH:"leaves a = ins_list x (leaves sub) ∧ aligned sep' a sep" using Ti IH by (auto) show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a @ leaves_list list @ leaves t" using h_split list_split Ti Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by (metis aligned_imp_Laligned) finallyshow ?case. next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned l (Node (ls'@(sub',sep')#(a,sep)#list) t) u" using Nil Cons list_conc list_split h_split Ti ls_split by simp moreoverhave"aligned l (Node (ls'@(sub',sep')#(a,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil ls_split using aligned_subst by fastforce ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves sub) ∧ aligned_upi sep' (Upi lt a rt) sep" using IH h_split list_split Cons sorted_inorder_sub by auto show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves lt @ leaves rt @ leaves_list list @ leaves t" using h_split list_split Upi Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by (metis aligned_imp_Laligned) finallyshow ?case. next case2 have"aligned_upi l (ins k x (Node ts t)) u = aligned_upi l (nodei k (ls'@(sub',sep')#(lt,a)#(rt,sep)#list) t) u" using Nil Cons list_conc list_split h_split Upi ls_split by simp moreoverhave"aligned l (Node (ls'@(sub',sep')#(lt,a)#(rt,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil ls_split align_subst_three by auto ultimatelyshow ?case using nodei_alignedby auto qed qed qed qed qed
lemma Laligned_insert_list: "sorted_less ks ==> x ≤ u ==> Laligned (Leaf ks) u ==> Laligned (Leaf (insert_list x ks)) u" using insert_list_req by (simp add: set_ins_list)
lemma Lalign_subst_two: "Laligned (Node (ts@[(sub,sep)]) t) u ==> aligned sep lt a==> aligned a rt u ==> Laligned (Node (ts@[(sub,sep),(lt,a)]) rt) u" apply(induction ts) apply (auto) by (meson align_subst_two aligned.simps(2))
lemma Lalign_subst_three: "Laligned (Node (ls@(subl,sepl)#(subr,sepr)#rs) t) u ==> aligned sepl lt a ==> aligned a rt sepr ==> Laligned (Node (ls@(subl,sepl)#(lt,a)#(rt,sepr)#rs) t) u" apply(induction ls) apply auto by (meson align_subst_three aligned.simps(2))
lemma Lnodei_Laligned: assumes"Laligned (Leaf ks) u" and"sorted_less ks" and"k > 0" shows"Laligned_upi (Lnodei k ks) u" using assms proof (cases "length ks ≤ 2*k") case False thenobtain ls sep rs where split_half_ts: "take ((length ks + 1) div 2) ks = ls@[sep]" "drop ((length ks + 1) div 2) ks = rs" using split_half_not_empty[of ks] by auto moreoverhave"sorted_less (ls@[sep])" by (metis append_take_drop_id assms(2) sorted_wrt_append split_half_ts(1)) ultimatelyhave"Laligned (Leaf (ls@[sep])) sep" using split_half_conc[of ks "ls@[sep]" rs] assms sorted_snoc_iff[of ls sep] by auto moreoverhave"aligned sep (Leaf rs) u" proof - have"length rs > 0" using False assms(3) split_half_ts(2) by fastforce thenobtain sep' rs' where"rs = sep' # rs'" by (cases rs) auto moreoverhave"sep < sep'" by (metis append_take_drop_id assms(2) calculation in_set_conv_decomp sorted_mid_iff sorted_snoc_iff split_half_ts(1) split_half_ts(2)) moreoverhave"sorted_less rs" by (metis append_take_drop_id assms(2) sorted_wrt_append split_half_ts(2)) ultimatelyshow ?thesis using split_half_ts split_half_conc[of ks "ls@[sep]" rs] assms by auto qed ultimatelyshow ?thesis using split_half_ts False by auto qed simp
lemma ins_Linorder: assumes"k > 0" and"Laligned t u" and"sorted_less (leaves t)" and"root_order k t" and"x ≤ u" shows"(leaves_upi (ins k x t)) = ins_list x (leaves t) ∧ Laligned_upi (ins k x t) u" using assms proof(induction k x t arbitrary: u rule: ins.induct) case (1 k x ks) thenshow ?case proof (safe, goal_cases) case _: 1 thenshow ?case using1 insert_list_req by auto next case2 from1have"Laligned (Leaf (insert_list x ks)) u" by (metis Laligned_insert_list leaves.simps(1)) moreoverhave"sorted_less (insert_list x ks)" using"1.prems"(3) split_set.insert_list_req split_set_axioms by auto ultimatelyshow ?case using Lnodei_Laligned[of "insert_list x ks" u k] 1 by (auto simp del: Lnodei.simps split_half.simps) qed next case (2 k x ts t) thenobtain ls rs where list_split: "split ts x = (ls,rs)" by (cases "split ts x") thenhave list_conc: "ts = ls@rs" using split_set.split_conc split_set_axioms by blast thenshow ?case proof (cases rs) case Nil thenobtain ts' sub' sep' where"ts = ts'@[(sub',sep')]" apply(cases ts) using2 list_conc Nil apply(simp) by (metis isin.cases list.distinct(1) rev_exhaust) have IH: "leaves_upi (ins k x t) = ins_list x (leaves t) ∧ aligned_upi sep' (ins k x t) u" (* this is now a case covered by the previous proof *) proof - (* we need to fulfill all these IH requirements *) note ins_inorder[of k] have"sorted_less (leaves t)" using"2.prems"(3) sorted_leaves_induct_last by blast moreoverhave"sep' < x" using split_req[of ts x] list_split by (metis "2.prems"(2) Laligned_sorted_separators ‹ts = ts' @ [(sub', sep')]›local.Nil self_append_conv sorted_snoc) moreoverhave"aligned sep' t u" using"2.prems"(2) Lalign_last ‹ts = ts' @ [(sub', sep')]›by blast ultimatelyshow ?thesis by (meson "2.prems"(1) "2.prems"(4) "2.prems"(5) ins_inorder order_impl_root_order root_order.simps(2)) qed show ?thesis proof (cases "ins k x t") case (Ti a) have IH: "leaves a = ins_list x (leaves t) ∧ aligned sep' a u" using IH Tiby force show ?thesis proof(safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a" using list_split Ti Nil by (auto simp add: list_conc) alsohave"… = leaves_list ls @ (ins_list x (leaves t))" by (simp add: IH) alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split using"2.prems" list_split Nil by auto finallyshow ?case . next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned (Node ts a) u" using Nil Ti list_split list_conc by simp moreoverhave"Laligned (Node ts a) u" using"2.prems"(2) by (metis IH ‹ts = ts' @ [(sub', sep')]› Laligned_subst_last) ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves t) ∧ aligned_upi sep' (Upi lt a rt) u" using IH by auto
show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves_upi (Upi lt a rt)" using list_split Upi Nil by (auto simp add: list_conc) alsohave"… = leaves_list ls @ ins_list x (leaves t)" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split using"2.prems" list_split local.Nil by auto finallyshow ?case. next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned_upi (nodei k (ts @ [(lt, a)]) rt) u" using Nil Upi list_split list_conc nodei_alignedby simp moreoverhave"Laligned (Node (ts@[(lt,a)]) rt) u" using"2.prems"(2) IH ‹ts = ts' @ [(sub', sep')]› Lalign_subst_two by fastforce ultimatelyshow ?case using nodei_Laligned by auto qed qed next case (Cons h list) thenobtain sub sep where h_split: "h = (sub,sep)" by (cases h)
thenhave sorted_inorder_sub: "sorted_less (leaves sub)" using"2.prems" list_conc Cons sorted_leaves_induct_subtree by fastforce moreoverhave order_sub: "order k sub" using"2.prems" list_conc Cons h_split by auto thenshow ?thesis (* TODO way to show this cleanly without distinguishing cases for ls? *) proof (cases ls) case Nil thenhave aligned_sub: "Laligned sub sep" using"2.prems"(2) list_conc h_split Cons by auto thenhave IH: "leaves_upi (ins k x sub) = ins_list x (leaves sub) ∧ Laligned_upi (ins k x sub) sep" proof - have"x ≤ sep" using"2.prems"(2) Laligned_sorted_separators h_split list_split local.Cons sorted_snoc split_set.split_req(3) split_set_axioms by blast thenshow ?thesis using"2.IH"(2)[OF sym[OF list_split] Cons sym[OF h_split], of sep] using"2.prems" list_split local.Nil aligned_sub sorted_inorder_sub order_sub using order_impl_root_order by auto qed thenshow ?thesis proof (cases "ins k x sub") case (Ti a) have IH:"leaves a = ins_list x (leaves sub) ∧ Laligned a sep" using Ti IH by (auto) show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a @ leaves_list list @ leaves t" using h_split list_split Ti Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by auto finallyshow ?case. next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned (Node ((a,sep)#list) t) u" using Nil Cons list_conc list_split h_split Tiby simp moreoverhave"Laligned (Node ((a,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil by auto ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves sub) ∧ Laligned_upi (Upi lt a rt) sep" using IH h_split list_split Cons sorted_inorder_sub by auto show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves lt @ leaves rt @ leaves_list list @ leaves t" using h_split list_split Upi Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by auto finallyshow ?case. next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned_upi (nodei k ((lt,a)#(rt,sep)#list) t) u" using Nil Cons list_conc list_split h_split Upiby simp moreoverhave"Laligned (Node ((lt,a)#(rt,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil by auto ultimatelyshow ?case using nodei_Lalignedby auto qed qed next case ls_split': Cons thenobtain ls' sub' sep' where ls_split: "ls = ls'@[(sub',sep')]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave aligned_sub: "aligned sep' sub sep" using"2.prems"(2) list_conc h_split Cons using Lalign_last Laligned_split_left by blast thenhave IH: "leaves_upi (ins k x sub) = ins_list x (leaves sub) ∧ aligned_upi sep' (ins k x sub) sep" proof - have"x ≤ sep" using"2.prems"(2) Laligned_sorted_separators h_split list_split local.Cons sorted_snoc split_set.split_req(3) split_set_axioms by blast moreoverhave"sep' < x" using"2.prems"(2) Laligned_sorted_separators list_split ls_split sorted_cons sorted_snoc split_set.split_req(2) split_set_axioms by blast ultimatelyshow ?thesis using"2.prems"(1) aligned_sub ins_inorder order_sub sorted_inorder_sub using order_impl_root_order by blast qed thenshow ?thesis proof (cases "ins k x sub") case (Ti a) have IH:"leaves a = ins_list x (leaves sub) ∧ aligned sep' a sep" using Ti IH by (auto) show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves a @ leaves_list list @ leaves t" using h_split list_split Ti Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by auto finallyshow ?case. next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned (Node (ls'@(sub',sep')#(a,sep)#list) t) u" using Nil Cons list_conc list_split h_split Ti ls_split by simp moreoverhave"Laligned (Node (ls'@(sub',sep')#(a,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil ls_split using Laligned_subst by fastforce ultimatelyshow ?case by auto qed next case (Upi lt a rt) thenhave IH:"leaves_upi (Upi lt a rt) = ins_list x (leaves sub) ∧ aligned_upi sep' (Upi lt a rt) sep" using IH h_split list_split Cons sorted_inorder_sub by auto show ?thesis proof (safe, goal_cases) case1 have"leaves_upi (ins k x (Node ts t)) = leaves_list ls @ leaves lt @ leaves rt @ leaves_list list @ leaves t" using h_split list_split Upi Cons by simp alsohave"… = leaves_list ls @ ins_list x (leaves sub) @ leaves_list list @ leaves t" using IH by simp alsohave"… = ins_list x (leaves (Node ts t))" using ins_list_split ins_list_split_right using list_split "2.prems" Cons h_split by auto finallyshow ?case. next case2 have"Laligned_upi (ins k x (Node ts t)) u = Laligned_upi (nodei k (ls'@(sub',sep')#(lt,a)#(rt,sep)#list) t) u" using Nil Cons list_conc list_split h_split Upi ls_split by simp moreoverhave"Laligned (Node (ls'@(sub',sep')#(lt,a)#(rt,sep)#list) t) u" using aligned_sub "2.prems"(2) IH h_split list_conc Cons Nil ls_split Lalign_subst_three by auto ultimatelyshow ?case using nodei_Lalignedby auto qed qed qed qed qed
lemma treei_bal: "bal_upi u ==> bal (treei u)" apply(cases u) apply(auto) done
lemma treei_order: "[k > 0; root_order_upi k u]==> root_order k (treei u)" apply(cases u) apply(auto simp add: order_impl_root_order) done
lemma treei_inorder: "inorder_upi u = inorder (treei u)" apply (cases u) apply auto done
lemma treei_leaves: "leaves_upi u = leaves (treei u)" apply (cases u) apply auto done
lemma treei_aligned: "aligned_upi l a u ==> aligned l (treei a) u" apply (cases a) apply auto done
lemma treei_Laligned: "Laligned_upi a u ==> Laligned (treei a) u" apply (cases a) apply auto done
lemma insert_bal: "bal t ==> bal (insert k x t)" using ins_bal by (simp add: treei_bal)
lemma insert_order: "[k > 0; sorted_less (leaves t); root_order k t]==> root_order k (insert k x t)" using ins_root_order by (simp add: treei_order)
lemma insert_inorder: assumes"k > 0""root_order k t""sorted_less (leaves t)""aligned l t u""l < x""x ≤u" shows"leaves (insert k x t) = ins_list x (leaves t)" and"aligned l (insert k x t) u" using ins_inorder assms by (simp_all add: treei_leaves treei_aligned)
lemma insert_Linorder: assumes"k > 0""root_order k t""sorted_less (leaves t)""Laligned t u""x ≤ u" shows"leaves (insert k x t) = ins_list x (leaves t)" and"Laligned (insert k x t) u" using ins_Linorder insert_inorder assms by (simp_all add: treei_leaves treei_Laligned)
corollary insert_Linorder_top: assumes"k > 0""root_order k t""sorted_less (leaves t)""Laligned t top" shows"leaves (insert k x t) = ins_list x (leaves t)" and"Laligned (insert k x t) top" using insert_Linorder top_greatest assms by simp_all
subsection"Deletion"
text"The following deletion method is inspired by Bauer (70) and Fielding (??). Rather than stealing only a single node from the neighbour, the neighbour is fully merged with the potentially underflowing node. If the resulting node is still larger than allowed, the merged node is split again, using the rules known from insertion splits. If the resulting node has admissable size, it is simply kept in the tree."
fun rebalance_middle_tree where "rebalance_middle_tree k ls (Leaf ms) sep rs (Leaf ts) = ( if length ms ≥ k ∧ length ts ≥ k then Node (ls@(Leaf ms,sep)#rs) (Leaf ts) else ( case rs of [] ==> ( case Lnodei k (ms@ts) of Ti u ==> Node ls u | Upi l a r ==> Node (ls@[(l,a)]) r) | (Leaf rrs,rsep)#rs ==> ( case Lnodei k (ms@rrs) of Ti u ==> Node (ls@(u,rsep)#rs) (Leaf ts) | Upi l a r ==> Node (ls@(l,a)#(r,rsep)#rs) (Leaf ts)) ))" | "rebalance_middle_tree k ls (Node mts mt) sep rs (Node tts tt) = ( if length mts ≥ k ∧ length tts ≥ k then Node (ls@(Node mts mt,sep)#rs) (Node tts tt) else ( case rs of [] ==> ( case nodei k (mts@(mt,sep)#tts) tt of Ti u ==> Node ls u | Upi l a r ==> Node (ls@[(l,a)]) r) | (Node rts rt,rsep)#rs ==> ( case nodei k (mts@(mt,sep)#rts) rt of Ti u ==> Node (ls@(u,rsep)#rs) (Node tts tt) | Upi l a r ==> Node (ls@(l,a)#(r,rsep)#rs) (Node tts tt)) ))"
text"All trees are merged with the right neighbour on underflow. Obviously for the last tree this would not work since it has no right neighbour. Therefore this tree, as the only exception, is merged with the left neighbour. However since we it does not make a difference, we treat the situation as if the second to last tree underflowed."
fun rebalance_last_tree where "rebalance_last_tree k ts t = ( case last ts of (sub,sep) ==> rebalance_middle_tree k (butlast ts) sub sep [] t )"
text"Rather than deleting the minimal key from the right subtree, we remove the maximal key of the left subtree. This is due to the fact that the last tree can easily be accessed and the left neighbour is way easier to access than the right neighbour, it resides in the same pair as the separating element to be removed."
fun del where "del k x (Leaf xs) = (Leaf (delete_list x xs))" | "del k x (Node ts t) = ( case split ts x of (ls,[]) ==> rebalance_last_tree k ls (del k x t) | (ls,(sub,sep)#rs) ==> ( rebalance_middle_tree k ls (del k x sub) sep rs t ) )"
fun reduce_root where "reduce_root (Leaf xs) = (Leaf xs)" | "reduce_root (Node ts t) = (case ts of [] ==> t | _ ==> (Node ts t) )"
fun delete where"delete k x t = reduce_root (del k x t)"
text"An invariant for intermediate states at deletion. In particular we allow for an underflow to 0 subtrees."
fun almost_order where "almost_order k (Leaf xs) = (length xs ≤ 2*k)" | "almost_order k (Node ts t) = ( (length ts ≤ 2*k) ∧ (∀s ∈ set (subtrees ts). order k s) ∧ order k t )"
text"Deletion proofs"
thm list.simps
lemma rebalance_middle_tree_height: assumes"height t = height sub" and"case rs of (rsub,rsep) # list ==> height rsub = height t | [] ==> True" shows"height (rebalance_middle_tree k ls sub sep rs t) = height (Node (ls@(sub,sep)#rs) t)" proof (cases "height t") case0 thenobtain ts subs where"t = Leaf ts""sub = Leaf subs"using height_Leaf assms by metis moreoverhave"rs = (rsub,rsep) # list ==> rsub = Node rts rt ==> False" for rsub rsep list rts rt proof (goal_cases) case1 thenhave"height rsub = height t" using assms(2) by auto thenhave"height rsub = 0" using0by simp thenshow ?case using"1"(2) height_Leaf by blast qed ultimatelyshow ?thesis by (auto split!: list.splits bplustree.splits) next case (Suc nat) thenobtain tts tt where t_node: "t = Node tts tt" using height_Leaf by (cases t) simp thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) simp thenshow ?thesis proof (cases "length mts ≥ k ∧ length tts ≥ k") case False thenshow ?thesis proof (cases rs) case Nil thenhave"height_upi (nodei k (mts@(mt,sep)#tts) tt) = height (Node (mts@(mt,sep)#tts) tt)" using nodei_heightby blast alsohave"… = max (height t) (height sub)" by (metis assms(1) height_upi.simps(2) height_list_split sub_node t_node) finallyhave height_max: "height_upi (nodei k (mts @ (mt, sep) # tts) tt) = max (height t) (height sub)"by simp thenshow ?thesis proof (cases "nodei k (mts@(mt,sep)#tts) tt") case (Ti u) thenhave"height u = max (height t) (height sub)"using height_max by simp thenhave"height (Node ls u) = height (Node (ls@[(sub,sep)]) t)" by (induction ls) (auto simp add: max.commute) thenshow ?thesis using Nil False Ti by (simp add: sub_node t_node) next case (Upi l a r) thenhave"height (Node (ls@[(sub,sep)]) t) = height (Node (ls@[(l,a)]) r)" using assms(1) height_max by (induction ls) auto thenshow ?thesis using Upi Nil sub_node t_node by auto qed next case (Cons a list) thenobtain rsub rsep where a_split: "a = (rsub, rsep)" by (cases a) thenobtain rts rt where r_node: "rsub = Node rts rt" using assms(2) Cons height_Leaf Suc by (cases rsub) simp_all
thenhave"height_upi (nodei k (mts@(mt,sep)#rts) rt) = height (Node (mts@(mt,sep)#rts) rt)" using nodei_heightby blast alsohave"… = max (height rsub) (height sub)" by (metis r_node height_upi.simps(2) height_list_split max.commute sub_node) finallyhave height_max: "height_upi (nodei k (mts @ (mt, sep) # rts) rt) = max (height rsub) (height sub)"by simp thenshow ?thesis proof (cases "nodei k (mts@(mt,sep)#rts) rt") case (Ti u) thenhave"height u = max (height rsub) (height sub)" using height_max by simp thenshow ?thesis using Ti False Cons r_node a_split sub_node t_node by auto next case (Upi l a r) thenhave height_max: "max (height l) (height r) = max (height rsub) (height sub)" using height_max by auto thenshow ?thesis using Cons a_split r_node Upi sub_node t_node by auto qed qed qed (simp add: sub_node t_node) qed
lemma rebalance_last_tree_height: assumes"height t = height sub" and"ts = list@[(sub,sep)]" shows"height (rebalance_last_tree k ts t) = height (Node ts t)" using rebalance_middle_tree_height assms by auto
lemma bal_sub_height: "bal (Node (ls@a#rs) t) ==> (case rs of [] ==> True | (sub,sep)#_ ==> height sub = height t)" by (cases rs) (auto)
lemma del_height: "[k > 0; root_order k t; bal t]==> height (del k x t) = height t" proof(induction k x t rule: del.induct) case (2 k x ts t) thenobtain ls list where list_split: "split ts x = (ls, list)"by (cases "split ts x") thenshow ?case proof(cases list) case Nil thenhave"height (del k x t) = height t" using2 list_split by (simp add: order_impl_root_order) moreoverobtain lls sub sep where"ls = lls@[(sub,sep)]" using split_conc 2 list_split Nil by (metis append_Nil2 less_nat_zero_code list.size(3) old.prod.exhaust rev_exhaust root_order.simps(2)) moreoverhave"Node ls t = Node ts t"using split_conc Nil list_split by auto ultimatelyshow ?thesis using rebalance_last_tree_height 2 list_split Nil split_conc by (auto simp add: max.assoc sup_nat_def max_def) next case (Cons a rs) thenhave rs_height: "case rs of [] ==> True | (rsub,rsep)#_ ==> height rsub = height t"(* notice the difference if rsub and t are switched *) using"2.prems"(3) bal_sub_height list_split split_conc by blast from Cons obtain sub sep where a_split: "a = (sub,sep)"by (cases a)
have height_t_sub: "height t = height sub" using"2.prems"(3) a_split list_split local.Cons split_set.split_set(1) split_set_axioms by fastforce have height_t_del: "height (del k x sub) = height t" by (metis "2.IH"(2) "2.prems"(1) "2.prems"(2) "2.prems"(3) a_split bal.simps(2) list_split local.Cons order_impl_root_order root_order.simps(2) some_child_sub(1) split_set(1)) thenhave"height (rebalance_middle_tree k ls (del k x sub) sep rs t) = height (Node (ls@((del k x sub),sep)#rs) t)" using rs_height rebalance_middle_tree_height by simp alsohave"… = height (Node (ls@(sub,sep)#rs) t)" using height_t_sub "2.prems" height_t_del by auto alsohave"… = height (Node ts t)" using2 a_split list_split Cons split_set(1) split_conc by auto finallyshow ?thesis using Cons a_split list_split 2 by simp qed qed simp
(* proof for inorders *)
(* note: this works (as it should, since there is not even recursion involved)
automatically. *yay* *) lemma rebalance_middle_tree_inorder: assumes"height t = height sub" and"case rs of (rsub,rsep) # list ==> height rsub = height t | [] ==> True" shows"leaves (rebalance_middle_tree k ls sub sep rs t) = leaves (Node (ls@(sub,sep)#rs) t)" apply(cases sub; cases t) using assms apply (auto
split!: bplustree.splits upi.splits list.splits
simp del: nodei.simps Lnodei.simps
simp add: nodei_leaves_simps Lnodei_leaves_simps
) done
lemma rebalance_last_tree_inorder: assumes"height t = height sub" and"ts = list@[(sub,sep)]" shows"leaves (rebalance_last_tree k ts t) = leaves (Node ts t)" using rebalance_middle_tree_inorder assms by auto
lemma butlast_inorder_app_id: "xs = xs' @ [(sub,sep)] ==> inorder_list xs' @ inorder sub @ [sep] = inorder_list xs" by simp
lemma height_bal_subtrees_merge: "[height (Node as a) = height (Node bs b); bal (Node as a); bal (Node bs b)] ==>∀x ∈ set (subtrees as) ∪ {a}. height x = height b" by (metis Suc_inject Un_iff bal.simps(2) height_bal_tree singletonD)
lemma bal_list_merge: assumes"bal_upi (Upi (Node as a) x (Node bs b))" shows"bal (Node (as@(a,x)#bs) b)" proof - have"∀x∈set (subtrees (as @ (a, x) # bs)). bal x" using subtrees_split assms by auto moreoverhave"bal b" using assms by auto moreoverhave"∀x∈set (subtrees as) ∪ {a} ∪ set (subtrees bs). height x = height b" using assms height_bal_subtrees_merge unfolding bal_upi.simps by blast ultimatelyshow ?thesis by auto qed
lemma nodei_bal_upi: assumes"bal_upi (nodei k ts t)" shows"bal (Node ts t)" using assms proof(cases "length ts ≤ 2*k") case False thenobtain ls sub sep rs where split_list: "split_half ts = (ls@[(sub,sep)], rs)" using nodei_casesby blast thenhave"nodei k ts t = Upi (Node ls sub) sep (Node rs t)" using False by auto moreoverhave"ts = ls@(sub,sep)#rs" by (metis append_Cons append_Nil2 append_eq_append_conv2 local.split_list same_append_eq split_half_conc) ultimatelyshow ?thesis using bal_list_merge[of ls sub sep rs t] assms by (simp del: bal.simps bal_upi.simps) qed simp
lemma nodei_bal_simp: "bal_upi (nodei k ts t) = bal (Node ts t)" using nodei_bal nodei_bal_upiby blast
lemma rebalance_middle_tree_bal: assumes"bal (Node (ls@(sub,sep)#rs) t)" shows"bal (rebalance_middle_tree k ls sub sep rs t)" proof (cases t) case t_node: (Leaf txs) thenobtain mxs where sub_node: "sub = Leaf mxs" using assms by (cases sub) (auto simp add: t_node) thenhave sub_heights: "height sub = height t""bal sub""bal t" apply (metis Suc_inject assms bal_split_left(1) bal_split_left(2) height_bal_tree) apply (meson assms bal.simps(2) bal_split_left(1)) using assms bal.simps(2) by blast show ?thesis proof (cases "length mxs ≥ k ∧ length txs ≥ k") case True thenshow ?thesis using t_node sub_node assms by (auto simp del: bal.simps) next case False thenshow ?thesis proof (cases rs) case Nil have"height_upi (Lnodei k (mxs@txs)) = height (Leaf (mxs@txs))" using Lnodei_heightby blast alsohave"… = 0" by simp alsohave"… = height t" using height_bal_tree sub_heights(3) t_node by fastforce finallyhave"height_upi (Lnodei k (mxs@txs)) = height t" . moreoverhave"bal_upi (Lnodei k (mxs@txs))" by (simp add: bal_upi.elims(3) height_Leaf height_upi.simps(2) max_nat.neutr_eq_iff) ultimatelyshow ?thesis apply (cases "Lnodei k (mxs@txs)") using assms Nil sub_node t_node by auto next case (Cons r rs) thenobtain rsub rsep where r_split: "r = (rsub,rsep)"by (cases r) thenhave rsub_height: "height rsub = height t""bal rsub" using assms Cons by auto thenobtain rxs where r_node: "rsub = Leaf rxs" apply(cases rsub) using assms t_node by auto have"height_upi (Lnodei k (mxs@rxs)) = height (Leaf (mxs@rxs))" using Lnodei_heightby blast alsohave"… = 0" by auto alsohave"… = height rsub" using height_bal_tree r_node rsub_height(2) by fastforce finallyhave1: "height_upi (Lnodei k (mxs@rxs)) = height rsub" . moreoverhave2: "bal_upi (Lnodei k (mxs@rxs))" by simp ultimatelyshow ?thesis proof (cases "Lnodei k (mxs@rxs)") case (Ti u) thenhave"bal (Node (ls@(u,rsep)#rs) t)" using12 Cons assms t_node subtrees_split sub_heights r_split rsub_height unfolding bal.simps by (auto simp del: height_bplustree.simps) thenshow ?thesis using Cons assms t_node sub_node r_split r_node False Ti by (auto simp del: nodei.simps bal.simps) next case (Upi l a r) thenhave"bal (Node (ls@(l,a)#(r,rsep)#rs) t)" using12 Cons assms t_node subtrees_split sub_heights r_split rsub_height unfolding bal.simps by (auto simp del: height_bplustree.simps) thenshow ?thesis using Cons assms t_node sub_node r_split r_node False Upi by (auto simp del: nodei.simps bal.simps) qed qed qed next case t_node: (Node tts tt) thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) (auto simp add: t_node) have sub_heights: "height sub = height t""bal sub""bal t" using assms by auto show ?thesis proof (cases "length mts ≥ k ∧ length tts ≥ k") case True thenshow ?thesis using t_node sub_node assms by (auto simp del: bal.simps) next case False thenshow ?thesis proof (cases rs) case Nil have"height_upi (nodei k (mts@(mt,sep)#tts) tt) = height (Node (mts@(mt,sep)#tts) tt)" using nodei_heightby blast alsohave"… = Suc (height tt)" by (metis height_bal_tree height_upi.simps(2) height_list_split max.idem sub_heights(1) sub_heights(3) sub_node t_node) alsohave"… = height t" using height_bal_tree sub_heights(3) t_node by fastforce finallyhave"height_upi (nodei k (mts@(mt,sep)#tts) tt) = height t"by simp moreoverhave"bal_upi (nodei k (mts@(mt,sep)#tts) tt)" by (metis bal_list_merge bal_upi.simps(2) nodei_bal sub_heights(1) sub_heights(2) sub_heights(3) sub_node t_node) ultimatelyshow ?thesis apply (cases "nodei k (mts@(mt,sep)#tts) tt") using assms Nil sub_node t_node by auto next case (Cons r rs) thenobtain rsub rsep where r_split: "r = (rsub,rsep)"by (cases r) thenhave rsub_height: "height rsub = height t""bal rsub" using assms Cons by auto thenobtain rts rt where r_node: "rsub = (Node rts rt)" apply(cases rsub) using t_node by simp have"height_upi (nodei k (mts@(mt,sep)#rts) rt) = height (Node (mts@(mt,sep)#rts) rt)" using nodei_heightby blast alsohave"… = Suc (height rt)" by (metis Un_iff ‹height rsub = height t› assms bal.simps(2) bal_split_last(1) height_bal_tree height_upi.simps(2) height_list_split list.set_intros(1) Cons max.idem r_node r_split set_append some_child_sub(1) sub_heights(1) sub_node) alsohave"… = height rsub" using height_bal_tree r_node rsub_height(2) by fastforce finallyhave1: "height_upi (nodei k (mts@(mt,sep)#rts) rt) = height rsub" . moreoverhave2: "bal_upi (nodei k (mts@(mt,sep)#rts) rt)" by (metis bal_list_merge bal_upi.simps(2) nodei_bal r_node rsub_height(1) rsub_height(2) sub_heights(1) sub_heights(2) sub_node) ultimatelyshow ?thesis proof (cases "nodei k (mts@(mt,sep)#rts) rt") case (Ti u) thenhave"bal (Node (ls@(u,rsep)#rs) t)" using12 Cons assms t_node subtrees_split sub_heights r_split rsub_height unfolding bal.simps by (auto simp del: height_bplustree.simps) thenshow ?thesis using Cons assms t_node sub_node r_split r_node False Ti by (auto simp del: nodei.simps bal.simps) next case (Upi l a r) thenhave"bal (Node (ls@(l,a)#(r,rsep)#rs) t)" using12 Cons assms t_node subtrees_split sub_heights r_split rsub_height unfolding bal.simps by (auto simp del: height_bplustree.simps) thenshow ?thesis using Cons assms t_node sub_node r_split r_node False Upi by (auto simp del: nodei.simps bal.simps) qed qed qed qed
lemma rebalance_last_tree_bal: "[bal (Node ts t); ts ≠ []]==> bal (rebalance_last_tree k ts t)" using rebalance_middle_tree_bal append_butlast_last_id[of ts] apply(cases "last ts") apply(auto simp del: bal.simps rebalance_middle_tree.simps) done
lemma Leaf_merge_aligned: "aligned l (Leaf ms) m ==> aligned m (Leaf rs) r ==> aligned l (Leaf (ms@rs)) r" by auto
lemma Node_merge_aligned: " inbetween aligned l mts mt sep ==> inbetween aligned sep tts tt u ==> inbetween aligned l (mts @ (mt, sep) # tts) tt u" apply(induction mts arbitrary: l) apply auto done
lemma aligned_subst_last_merge: "aligned l (Node (ts'@[(sub', sep'),(sub,sep)]) t) u ==> aligned sep' t' u ==> aligned l (Node (ts'@[(sub', sep')]) t') u" apply (induction ts' arbitrary: l) apply auto done
lemma aligned_subst_last_merge_two: "aligned l (Node (ts@[(sub',sep'),(sub,sep)]) t) u ==> aligned sep' lt a ==> aligned a rt u ==> aligned l (Node (ts@[(sub',sep'),(lt,a)]) rt) u" apply(induction ts arbitrary: l) apply auto done
lemma aligned_subst_merge: "aligned l (Node (ls@(lsub, lsep)#(sub,sep)#(rsub,rsep)#rs) t) u ==> aligned lsep sub' rsep ==> aligned l (Node (ls@(lsub, lsep)#(sub', rsep)#rs) t) u" apply (induction ls arbitrary: l) apply auto done
lemma aligned_subst_merge_two: "aligned l (Node (ls@(lsub, lsep)#(sub,sep)#(rsub,rsep)#rs) t) u ==> aligned lsep sub' a ==> aligned a rsub' rsep ==> aligned l (Node (ls@(lsub, lsep)#(sub',a)#(rsub', rsep)#rs) t) u" apply(induction ls arbitrary: l) apply auto done
lemma rebalance_middle_tree_aligned: assumes"aligned l (Node (ls@(sub,sep)#rs) t) u" and"height t = height sub" and"sorted_less (leaves (Node (ls@(sub,sep)#rs) t))" and"k > 0" and"case rs of (rsub,rsep) # list ==> height rsub = height t | [] ==> True" shows"aligned l (rebalance_middle_tree k ls sub sep rs t) u" proof (cases t) case t_node: (Leaf txs) thenobtain mxs where sub_node: "sub = Leaf mxs" using assms by (cases sub) (auto simp add: t_node) show ?thesis proof (cases "length mxs ≥ k ∧ length txs ≥ k") case True thenshow ?thesis using t_node sub_node assms by (auto simp del: bal.simps) next case False thenshow ?thesis proof (cases rs) case rs_nil: Nil thenhave sorted_leaves: "sorted_less (mxs@txs)" using assms(3) rs_nil t_node sub_node sorted_wrt_append by auto thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"aligned l (Leaf (mxs@txs)) u" using t_node sub_node assms rs_nil False using assms by auto thenhave"aligned_upi l (Lnodei k (mxs@txs)) u" using Lnodei_aligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_nil ls_nil by (auto simp del: Lnodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Leaf (mxs@txs)) u" using Leaf_merge_aligned using align_last aligned_split_left assms(1) t_node rs_nil sub_node by blast moreoverhave"sorted_less (mxs@txs)" using assms(3) rs_nil t_node sub_node by (auto simp add: sorted_wrt_append) ultimatelyhave"aligned_upi lsep (Lnodei k (mxs@txs)) u" using Lnodei_aligned assms(4) by blast thenshow ?thesis using False t_node sub_node rs_nil ls_Cons assms using aligned_subst_last_merge[of l ls' lsub lsep sub sep t u] using aligned_subst_last_merge_two[of l ls' lsub lsep sub sep t u] by (auto simp del: Lnodei.simps split!: upi.split) qed next case rs_Cons: (Cons r rs) thenobtain rsub rsep where r_split[simp]: "r = (rsub,rsep)"by (cases r) thenhave"height rsub = 0" using‹∧thesis. (∧mxs. sub = Leaf mxs ==> thesis) ==> thesis› assms(2) assms(5) rs_Cons by fastforce thenobtain rxs where rs_Leaf[simp]: "rsub = Leaf rxs" by (cases rsub) auto thenhave sorted_leaves: "sorted_less (mxs@rxs)" using assms(3) rs_Cons sub_node sorted_wrt_append r_split by (auto simp add: sorted_wrt_append) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"aligned l (Leaf (mxs@rxs)) rsep" using sub_node assms rs_Cons False by auto thenhave"aligned_upi l (Lnodei k (mxs@rxs)) rsep" using Lnodei_aligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_nil assms by (auto simp del: Lnodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Leaf (mxs@rxs)) rsep" using Leaf_merge_aligned using align_last aligned_split_left assms(1) t_node rs_Cons sub_node by (metis aligned.elims(2) aligned_split_right bplustree.distinct(1) bplustree.inject(2) inbetween.simps(2) r_split rs_Leaf) thenhave"aligned_upi lsep (Lnodei k (mxs@rxs)) rsep" using Lnodei_aligned assms(4) sorted_leaves by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_Cons assms using aligned_subst_merge[of l ls' lsub lsep sub sep rsub rsep rs] using aligned_subst_merge_two[of l ls' lsub lsep sub sep rsub rsep rs t u] by (auto simp del: Lnodei.simps split!: upi.split) qed qed qed next case t_node: (Node tts tt) thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) (auto simp add: t_node) show ?thesis proof (cases "length tts ≥ k ∧ length mts ≥ k") case True thenshow ?thesis using t_node sub_node assms by (auto simp del: bal.simps) next case False thenshow ?thesis proof (cases rs) case rs_nil: Nil thenhave sorted_leaves: "sorted_less (leaves_list mts @ leaves mt @ leaves_list tts @ leaves tt)" using assms(3) rs_nil t_node sub_node by (auto simp add: sorted_wrt_append) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"aligned l (Node (mts@(mt,sep)#tts) tt) u" using t_node sub_node assms rs_nil False by (auto simp add: Node_merge_aligned) thenhave"aligned_upi l (nodei k (mts@(mt,sep)#tts) tt) u" using nodei_aligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_nil ls_nil by (auto simp del: nodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Node (mts@(mt,sep)#tts) tt) u" using t_node sub_node assms rs_nil False ls_Cons by (metis Node_merge_aligned align_last aligned.simps(2) aligned_split_left) thenhave"aligned_upi lsep (nodei k (mts@(mt,sep)#tts) tt) u" using nodei_aligned assms(4) sorted_leaves by blast thenshow ?thesis using False t_node sub_node rs_nil ls_Cons assms using aligned_subst_last_merge[of l ls' lsub lsep sub sep t u] using aligned_subst_last_merge_two[of l ls' lsub lsep sub sep t u] by (auto simp del: nodei.simps split!: upi.split) qed next case rs_Cons: (Cons r rs) thenobtain rsub rsep where r_split[simp]: "r = (rsub,rsep)" by (cases r) thenhave"height rsub ≠ 0" using assms rs_Cons t_node by auto thenobtain rts rt where rs_Node: "rsub = Node rts rt" by (cases rsub) auto have"sorted_less (leaves sub @ leaves rsub)" using assms(3) rs_Cons r_split by (simp add: sorted_wrt_append) thenhave sorted_leaves: "sorted_less (leaves_list mts @ leaves mt @ leaves_list rts @ leaves rt)" by (simp add: rs_Node sub_node) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"aligned l (Node (mts@(mt,sep)#rts) rt) rsep" using sub_node assms rs_Cons False rs_Node by (metis Node_merge_aligned aligned.simps(2) append_self_conv2 inbetween.simps(2) r_split) thenhave"aligned_upi l (nodei k (mts@(mt,sep)#rts) rt) rsep" using nodei_aligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_nil assms rs_Node by (auto simp del: nodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Node (mts@(mt,sep)#rts) rt) rsep" using Node_merge_aligned using align_last aligned_split_left assms(1) t_node rs_Cons sub_node by (metis aligned.simps(2) aligned_split_right inbetween.simps(2) r_split rs_Node) thenhave"aligned_upi lsep (nodei k (mts@(mt,sep)#rts) rt) rsep" using sorted_leaves nodei_aligned assms(4) by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_Cons assms rs_Node using aligned_subst_merge[of l ls' lsub lsep sub sep rsub rsep rs] using aligned_subst_merge_two[of l ls' lsub lsep sub sep rsub rsep rs t u] by (auto simp del: nodei.simps split!: upi.split) qed qed qed qed
lemma Node_merge_Laligned: " Laligned (Node mts mt) sep ==> inbetween aligned sep tts tt u ==> Laligned (Node (mts @ (mt, sep) # tts) tt) u" apply(induction mts) apply auto using Node_merge_aligned by blast
lemma Laligned_subst_last_merge: "Laligned (Node (ts'@[(sub', sep'),(sub,sep)]) t) u ==> aligned sep' t' u ==> Laligned (Node (ts'@[(sub', sep')]) t') u" apply (induction ts') apply auto by (metis (no_types, opaque_lifting) Node_merge_aligned aligned.simps(2) aligned_split_left inbetween.simps(1))
lemma Laligned_subst_last_merge_two: "Laligned (Node (ts@[(sub',sep'),(sub,sep)]) t) u ==> aligned sep' lt a ==> aligned a rt u ==> Laligned (Node (ts@[(sub',sep'),(lt,a)]) rt) u" apply(induction ts) apply auto by (meson aligned.simps(2) aligned_subst_last_merge_two)
lemma Laligned_subst_merge: "Laligned (Node (ls@(lsub, lsep)#(sub,sep)#(rsub,rsep)#rs) t) u ==> aligned lsep sub' rsep ==> Laligned (Node (ls@(lsub, lsep)#(sub', rsep)#rs) t) u" apply (induction ls) apply auto by (meson aligned.simps(2) aligned_subst_merge)
lemma Laligned_subst_merge_two: "Laligned (Node (ls@(lsub, lsep)#(sub,sep)#(rsub,rsep)#rs) t) u ==> aligned lsep sub' a ==> aligned a rsub' rsep ==> Laligned (Node (ls@(lsub, lsep)#(sub',a)#(rsub', rsep)#rs) t) u" apply(induction ls) apply auto by (meson aligned.simps(2) aligned_subst_merge_two)
lemma rebalance_middle_tree_Laligned: assumes"Laligned (Node (ls@(sub,sep)#rs) t) u" and"height t = height sub" and"sorted_less (leaves (Node (ls@(sub,sep)#rs) t))" and"k > 0" and"case rs of (rsub,rsep) # list ==> height rsub = height t | [] ==> True" shows"Laligned (rebalance_middle_tree k ls sub sep rs t) u" proof (cases t) case t_node: (Leaf txs) thenobtain mxs where sub_node: "sub = Leaf mxs" using assms by (cases sub) (auto simp add: t_node) show ?thesis proof (cases "length mxs ≥ k ∧ length txs ≥ k") case True thenshow ?thesis using t_node sub_node assms by auto next case False thenshow ?thesis proof (cases rs) case rs_nil: Nil thenhave sorted_leaves: "sorted_less (mxs@txs)" using assms(3) rs_nil t_node sub_node sorted_wrt_append by auto thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"Laligned (Leaf (mxs@txs)) u" using t_node sub_node assms rs_nil False using assms by auto thenhave"Laligned_upi (Lnodei k (mxs@txs)) u" using Lnodei_Laligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_nil ls_nil by (auto simp del: Lnodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Leaf (mxs@txs)) u" using Leaf_merge_aligned Lalign_last Laligned_split_left assms(1) rs_nil sub_node t_node by blast moreoverhave"sorted_less (mxs@txs)" using assms(3) rs_nil t_node sub_node by (auto simp add: sorted_wrt_append) ultimatelyhave"aligned_upi lsep (Lnodei k (mxs@txs)) u" using Lnodei_aligned assms(4) by blast thenshow ?thesis using False t_node sub_node rs_nil ls_Cons assms using Laligned_subst_last_merge[of ls' lsub lsep sub sep t u] using Laligned_subst_last_merge_two[of ls' lsub lsep sub sep t u] by (auto simp del: Lnodei.simps split!: upi.split) qed next case rs_Cons: (Cons r rs) thenobtain rsub rsep where r_split[simp]: "r = (rsub,rsep)"by (cases r) thenhave"height rsub = 0" using‹∧thesis. (∧mxs. sub = Leaf mxs ==> thesis) ==> thesis› assms(2) assms(5) rs_Cons by fastforce thenobtain rxs where rs_Leaf[simp]: "rsub = Leaf rxs" by (cases rsub) auto thenhave sorted_leaves: "sorted_less (mxs@rxs)" using assms(3) rs_Cons sub_node sorted_wrt_append r_split by (auto simp add: sorted_wrt_append) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"Laligned (Leaf (mxs@rxs)) rsep" using sub_node assms rs_Cons False by auto thenhave"Laligned_upi (Lnodei k (mxs@rxs)) rsep" using Lnodei_Laligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_nil assms by (auto simp del: Lnodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Leaf (mxs@rxs)) rsep" using Leaf_merge_aligned using assms(1) t_node rs_Cons sub_node by (metis Lalign_last Laligned_split_left Laligned_split_right aligned.elims(2) bplustree.distinct(1) bplustree.inject(2) inbetween.simps(2) r_split rs_Leaf) thenhave"aligned_upi lsep (Lnodei k (mxs@rxs)) rsep" using Lnodei_aligned assms(4) sorted_leaves by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_Cons assms using Laligned_subst_merge[of ls' lsub lsep sub sep rsub rsep rs] using Laligned_subst_merge_two[of ls' lsub lsep sub sep rsub rsep rs t u] by (auto simp del: Lnodei.simps split!: upi.split) qed qed qed next case t_node: (Node tts tt) thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) (auto simp add: t_node) show ?thesis proof (cases "length tts ≥ k ∧ length mts ≥ k") case True thenshow ?thesis using t_node sub_node assms by (auto simp del: bal.simps) next case False thenshow ?thesis proof (cases rs) case rs_nil: Nil thenhave sorted_leaves: "sorted_less (leaves_list mts @ leaves mt @ leaves_list tts @ leaves tt)" using assms(3) rs_nil t_node sub_node by (auto simp add: sorted_wrt_append) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"Laligned (Node (mts@(mt,sep)#tts) tt) u" using t_node sub_node assms rs_nil False by (metis Lalign_last Laligned_nonempty_Node Node_merge_Laligned aligned.simps(2) append_self_conv2) thenhave"Laligned_upi (nodei k (mts@(mt,sep)#tts) tt) u" using nodei_Laligned sorted_leaves assms by blast thenshow ?thesis using False t_node sub_node rs_nil ls_nil by (auto simp del: nodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Node (mts@(mt,sep)#tts) tt) u" using t_node sub_node assms rs_nil False ls_Cons by (metis Lalign_last Laligned_split_left Node_merge_aligned aligned.simps(2)) thenhave"aligned_upi lsep (nodei k (mts@(mt,sep)#tts) tt) u" using nodei_aligned assms(4) sorted_leaves by blast thenshow ?thesis using False t_node sub_node rs_nil ls_Cons assms using Laligned_subst_last_merge[of ls' lsub lsep sub sep t u] using Laligned_subst_last_merge_two[of ls' lsub lsep sub sep t u] by (auto simp del: nodei.simps bal.simps height_bplustree.simps split!: upi.split list.splits) qed next case rs_Cons: (Cons r rs) thenobtain rsub rsep where r_split[simp]: "r = (rsub,rsep)" by (cases r) thenhave"height rsub ≠ 0" using assms rs_Cons t_node by auto thenobtain rts rt where rs_Node: "rsub = Node rts rt" by (cases rsub) auto have"sorted_less (leaves sub @ leaves rsub)" using assms(3) rs_Cons r_split by (simp add: sorted_wrt_append) thenhave sorted_leaves: "sorted_less (leaves_list mts @ leaves mt @ leaves_list rts @ leaves rt)" by (simp add: rs_Node sub_node) thenshow ?thesis proof (cases ls) case ls_nil: Nil thenhave"Laligned (Node (mts@(mt,sep)#rts) rt) rsep" using sub_node assms rs_Cons False rs_Node by (metis Laligned_nonempty_Node Node_merge_Laligned aligned.simps(2) append_self_conv2 inbetween.simps(2) r_split) thenhave"Laligned_upi (nodei k (mts@(mt,sep)#rts) rt) rsep" using nodei_Lalignedby blast thenshow ?thesis using False t_node sub_node rs_Cons ls_nil assms rs_Node by (auto simp del: nodei.simps split!: upi.split) next case Cons thenobtain ls' lsub lsep where ls_Cons: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep (Node (mts@(mt,sep)#rts) rt) rsep" using Node_merge_aligned using assms(1) t_node rs_Cons sub_node by (metis Lalign_last Laligned_split_left Laligned_split_right aligned.simps(2) inbetween.simps(2) r_split rs_Node) thenhave"aligned_upi lsep (nodei k (mts@(mt,sep)#rts) rt) rsep" using sorted_leaves nodei_aligned assms(4) by blast thenshow ?thesis using False t_node sub_node rs_Cons ls_Cons assms rs_Node using Laligned_subst_merge[of ls' lsub lsep sub sep rsub rsep rs] using Laligned_subst_merge_two[of ls' lsub lsep sub sep rsub rsep rs t u] by (auto simp del: nodei.simps split!: upi.split) qed qed qed qed
lemma rebalance_last_tree_aligned: assumes"aligned l (Node (ls@[(sub,sep)]) t) u" and"height t = height sub" and"sorted_less (leaves (Node (ls@[(sub,sep)]) t))" and"k > 0" shows"aligned l (rebalance_last_tree k (ls@[(sub,sep)]) t) u" using rebalance_middle_tree_aligned[of l ls sub sep "[]" t u k] assms by auto
lemma rebalance_last_tree_Laligned: assumes"Laligned (Node (ls@[(sub,sep)]) t) u" and"height t = height sub" and"sorted_less (leaves (Node (ls@[(sub,sep)]) t))" and"k > 0" shows"Laligned (rebalance_last_tree k (ls@[(sub,sep)]) t) u" using rebalance_middle_tree_Laligned[of ls sub sep "[]" t u k] assms by auto
lemma del_bal: assumes"k > 0" and"root_order k t" and"bal t" shows"bal (del k x t)" using assms proof(induction k x t rule: del.induct) case (2 k x ts t) thenobtain ls rs where list_split: "split ts x = (ls,rs)" by (cases "split ts x") thenshow ?case proof (cases rs) case Nil thenhave"bal (del k x t)"using2 list_split by (simp add: order_impl_root_order) moreoverhave"height (del k x t) = height t" using2 del_height by (simp add: order_impl_root_order) moreoverhave"ts ≠ []"using2by auto ultimatelyhave"bal (rebalance_last_tree k ts (del k x t))" using2 Nil rebalance_last_tree_bal by simp thenhave"bal (rebalance_last_tree k ls (del k x t))" using list_split split_conc Nil by fastforce thenshow ?thesis using2 list_split Nil by auto next case (Cons r rs) thenobtain sub sep where r_split: "r = (sub,sep)"by (cases r) thenhave sub_height: "height sub = height t""bal sub" using2 Cons list_split split_set(1) by fastforce+ thenhave"bal (del k x sub)""height (del k x sub) = height sub"using sub_height apply (metis "2.IH"(2) "2.prems"(1) "2.prems"(2) list_split local.Cons order_impl_root_order r_split root_order.simps(2) some_child_sub(1) split_set(1)) by (metis "2.prems"(1) "2.prems"(2) list_split Cons order_impl_root_order r_split root_order.simps(2) some_child_sub(1) del_height split_set(1) sub_height(2)) moreoverhave"bal (Node (ls@(sub,sep)#rs) t)" using"2.prems"(3) list_split Cons r_split split_conc by blast ultimatelyhave"bal (Node (ls@(del k x sub,sep)#rs) t)" using bal_substitute_subtree[of ls sub sep rs t "del k x sub"] by metis thenhave"bal (rebalance_middle_tree k ls (del k x sub) sep rs t)" using rebalance_middle_tree_bal[of ls "del k x sub" sep rs t k] by metis thenshow ?thesis using2 list_split Cons r_split by auto qed qed simp
lemma rebalance_middle_tree_order: assumes"almost_order k sub" and"∀s ∈ set (subtrees (ls@rs)). order k s""order k t" and"case rs of (rsub,rsep) # list ==> height rsub = height t | [] ==> True" and"length (ls@(sub,sep)#rs) ≤ 2*k" and"height sub = height t" shows"almost_order k (rebalance_middle_tree k ls sub sep rs t)" proof(cases t) case (Leaf txs) thenobtain subxs where"sub = Leaf subxs" using height_Leaf assms by metis thenshow ?thesis using assms Leaf by (auto split!: list.splits bplustree.splits) next case t_node: (Node tts tt) thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) (auto) thenshow ?thesis proof(cases "length mts ≥ k ∧ length tts ≥ k") case True thenhave"order k sub"using assms by (simp add: sub_node) thenshow ?thesis using True t_node sub_node assms by auto next case False thenshow ?thesis proof (cases rs) case Nil have"order_upi k (nodei k (mts@(mt,sep)#tts) tt)" using nodei_order[of k "mts@(mt,sep)#tts" tt] assms(1,3) t_node sub_node by (auto simp del: order_upi.simps nodei.simps) thenshow ?thesis apply(cases "nodei k (mts@(mt,sep)#tts) tt") using assms t_node sub_node False Nil apply (auto simp del: nodei.simps) done next case (Cons r rs) thenobtain rsub rsep where r_split: "r = (rsub,rsep)"by (cases r) thenhave rsub_height: "height rsub = height t" using assms Cons by auto thenobtain rts rt where r_node: "rsub = (Node rts rt)" apply(cases rsub) using t_node by simp have"order_upi k (nodei k (mts@(mt,sep)#rts) rt)" using nodei_order[of k "mts@(mt,sep)#rts" rt] assms(1,2) t_node sub_node r_node r_split Cons by (auto simp del: order_upi.simps nodei.simps) thenshow ?thesis apply(cases "nodei k (mts@(mt,sep)#rts) rt") using assms t_node sub_node False Cons r_split r_node apply (auto simp del: nodei.simps) done qed qed qed
(* we have to proof the order invariant once for an underflowing last tree *) lemma rebalance_middle_tree_last_order: assumes"almost_order k t" and"∀s ∈ set (subtrees (ls@(sub,sep)#rs)). order k s" and"rs = []" and"length (ls@(sub,sep)#rs) ≤ 2*k" and"height sub = height t" shows"almost_order k (rebalance_middle_tree k ls sub sep rs t)" proof (cases t) case (Leaf txs) thenobtain subxs where"sub = Leaf subxs" using height_Leaf assms by metis thenshow ?thesis using assms Leaf by (auto split!: list.splits bplustree.splits) next case t_node: (Node tts tt) thenobtain mts mt where sub_node: "sub = Node mts mt" using assms by (cases sub) (auto) thenshow ?thesis proof(cases "length mts ≥ k ∧ length tts ≥ k") case True thenhave"order k sub"using assms by (simp add: sub_node) thenshow ?thesis using True t_node sub_node assms by auto next case False have"order_upi k (nodei k (mts@(mt,sep)#tts) tt)" using nodei_order[of k "mts@(mt,sep)#tts" tt] assms t_node sub_node by (auto simp del: order_upi.simps nodei.simps) thenshow ?thesis apply(cases "nodei k (mts@(mt,sep)#tts) tt") using assms t_node sub_node False Nil apply (auto simp del: nodei.simps) done qed qed
lemma rebalance_last_tree_order: assumes"ts = ls@[(sub,sep)]" and"∀s ∈ set (subtrees (ts)). order k s""almost_order k t" and"length ts ≤ 2*k" and"height sub = height t" shows"almost_order k (rebalance_last_tree k ts t)" using rebalance_middle_tree_last_order assms by auto
lemma del_order: assumes"k > 0" and"root_order k t" and"bal t" and"sorted (leaves t)" shows"almost_order k (del k x t)" using assms proof (induction k x t rule: del.induct) case (1 k x xs) thenshow ?case by auto next case (2 k x ts t) thenobtain ls list where list_split: "split ts x = (ls, list)"by (cases "split ts x") thenshow ?case proof (cases list) case Nil thenhave"almost_order k (del k x t)"using2 list_split by (simp add: order_impl_root_order sorted_wrt_append) moreoverobtain lls lsub lsep where ls_split: "ls = lls@[(lsub,lsep)]" using2 Nil list_split by (metis append_Nil length_0_conv less_nat_zero_code old.prod.exhaust rev_exhaust root_order.simps(2) split_conc) moreoverhave"height t = height (del k x t)"using del_height 2 by (simp add: order_impl_root_order) moreoverhave"length ls = length ts" using Nil list_split by (auto dest: split_length) ultimatelyhave"almost_order k (rebalance_last_tree k ls (del k x t))" using rebalance_last_tree_order[of ls lls lsub lsep k "del k x t"] by (metis "2.prems"(2) "2.prems"(3) Un_iff append_Nil2 bal.simps(2) list_split Nil root_order.simps(2) singletonI split_conc subtrees_split) thenshow ?thesis using2 list_split Nil by auto next case (Cons r rs)
from Cons obtain sub sep where r_split: "r = (sub,sep)"by (cases r)
have inductive_help: "case rs of [] ==> True | (rsub,rsep)#_ ==> height rsub = height t" "∀s∈set (subtrees (ls @ rs)). order k s" "Suc (length (ls @ rs)) ≤ 2 * k" "order k t" using Cons r_split "2.prems" list_split split_set by (auto dest: split_conc split!: list.splits) thenhave"almost_order k (del k x sub)"using2 list_split Cons r_split order_impl_root_order by (metis bal.simps(2) root_order.simps(2) some_child_sub(1) sorted_leaves_induct_subtree split_conc split_set(1)) moreoverhave"height (del k x sub) = height t" by (metis "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) list_split Cons order_impl_root_order r_split root_order.simps(2) some_child_sub(1) del_height split_set(1)) ultimatelyhave"almost_order k (rebalance_middle_tree k ls (del k x sub) sep rs t)" using rebalance_middle_tree_order[of k "del k x sub" ls rs t sep] using inductive_help using Cons r_split list_split by auto thenshow ?thesis using2 Cons r_split list_split by auto qed qed
(* sortedness of delete by inorder *) (* generalize del_list_sorted since its cumbersome to express inorder_list ts as xs @ [a] notethattheproofschemeisalmostidenticaltoins_list_sorted
*) (* TODO lift to leaves *) thm del_list_sorted
lemma del_list_split: assumes"Laligned (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, rs)" shows"del_list x (leaves (Node ts t)) = leaves_list ls @ del_list x (leaves_list rs @ leaves t)" proof (cases ls) case Nil thenshow ?thesis using assms by (auto dest!: split_conc) next case Cons thenobtain ls' sub sep where ls_tail_split: "ls = ls' @ [(sub,sep)]" by (metis list.distinct(1) rev_exhaust surj_pair) have sorted_inorder: "sorted_less (inorder (Node ts t))" using Laligned_sorted_inorder assms(1) sorted_cons sorted_snoc by blast moreoverhave"sep < x" using split_req(2)[of ts x ls' sub sep rs] using assms ls_tail_split sorted_inorder sorted_inorder_separators by blast moreoverhave leaves_split: "leaves (Node ts t) = leaves_list ls @ leaves_list rs @ leaves t" using assms(3) split_tree.leaves_split by blast thenshow ?thesis proof (cases "leaves_list ls") case Nil thenshow ?thesis by (metis append_self_conv2 leaves_split) next case Cons thenobtain leavesls' l' where leaves_tail_split: "leaves_list ls = leavesls' @ [l']" by (metis list.simps(3) rev_exhaust) thenhave"l' ≤ sep" proof - have"l' ∈ set (leaves_list ls)" using leaves_tail_split by force thenhave"l' ∈ set (leaves (Node ls' sub))" using ls_tail_split by auto moreoverhave"Laligned (Node ls' sub) sep" using assms split_conc[OF assms(3)] Cons ls_tail_split using Laligned_split_left by simp ultimatelyshow ?thesis using Laligned_leaves_inbetween[of "Node ls' sub" sep] by blast qed moreoverhave"sorted_less (leaves (Node ts t))" using assms sorted_wrt_append split_conc by fastforce ultimatelyshow ?thesis using assms(2) split_conc[OF assms(3)] leaves_tail_split using del_list_sorted[of "leavesls'" l' "leaves_list rs @ leaves t" x] ‹sep < x› by auto qed qed
corollary del_list_split_aligned: assumes"aligned l (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, rs)" shows"del_list x (leaves (Node ts t)) = leaves_list ls @ del_list x (leaves_list rs @ leaves t)" using aligned_imp_Laligned assms(1) assms(2) assms(3) del_list_split by blast
(* del sorted requires sortedness of the full list so we need to change the right specialization a bit *)
lemma del_list_split_right: assumes"Laligned (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, (sub,sep)#rs)" shows"del_list x (leaves_list ((sub,sep)#rs) @ leaves t) = del_list x (leaves sub) @ leaves_list rs @ leaves t" proof - have sorted_inorder: "sorted_less (inorder (Node ts t))" using Laligned_sorted_inorder assms(1) sorted_cons sorted_snoc by blast from assms have"x ≤ sep" proof - from assms have"sorted_less (separators ts)" using sorted_inorder_separators sorted_inorder by blast thenshow ?thesis using split_req(3) using assms by fastforce qed thenshow ?thesis proof (cases "leaves_list rs @ leaves t") case Nil moreoverhave"leaves_list ((sub,sep)#rs) @ leaves t = leaves sub @ leaves_list rs @ leaves t" by simp ultimatelyshow ?thesis by (metis self_append_conv) next case (Cons r' rs') thenhave"sep < r'" by (metis aligned_leaves_inbetween Laligned_split_right assms(1) assms(3) leaves.simps(2) list.set_intros(1) split_set.split_conc split_set_axioms) thenhave"x < r'" using‹x ≤ sep›by auto moreoverhave"sorted_less (leaves sub @ leaves_list rs @ leaves t)" proof - have"sorted_less (leaves_list ls @ leaves sub @ leaves_list rs @ leaves t)" using assms by (auto dest!: split_conc) thenshow ?thesis using assms by (metis Cons sorted_wrt_append) qed ultimatelyshow ?thesis using del_list_sorted[of "leaves sub" r' rs'] Cons by auto qed qed
corollary del_list_split_right_aligned: assumes"aligned l (Node ts t) u" and"sorted_less (leaves (Node ts t))" and"split ts x = (ls, (sub,sep)#rs)" shows"del_list x (leaves_list ((sub,sep)#rs) @ leaves t) = del_list x (leaves sub) @ leaves_list rs @ leaves t" using aligned_imp_Laligned assms(1) assms(2) assms(3) split_set.del_list_split_right split_set_axioms by blast
thm del_list_idem
lemma del_inorder: assumes"k > 0" and"root_order k t" and"bal t" and"sorted_less (leaves t)" and"aligned l t u" and"l < x""x ≤ u" shows"leaves (del k x t) = del_list x (leaves t) ∧ aligned l (del k x t) u" using assms proof (induction k x t arbitrary: l u rule: del.induct) case (1 k x xs) thenhave"leaves (del k x (Leaf xs)) = del_list x (leaves (Leaf xs))" by (simp add: insert_list_req) moreoverhave"aligned l (del k x (Leaf xs)) u" proof - have"l < u" using"1.prems"(6) "1.prems"(7) by auto moreoverhave"∀x ∈ set xs - {x}. l < x ∧ x ≤ u" using"1.prems"(5) by auto ultimatelyshow ?thesis using set_del_list insert_list_req by (metis "1"(4) aligned.simps(1) del.simps(1) leaves.simps(1)) qed ultimatelyshow ?case by simp next case (2 k x ts t l u) thenobtain ls rs where list_split: "split ts x = (ls, rs)" by (meson surj_pair) thenhave list_conc: "ts = ls @ rs" using split_set.split_conc split_set_axioms by blast show ?case proof (cases rs) case Nil thenobtain ls' lsub lsep where ls_split: "ls = ls' @ [(lsub,lsep)]" by (metis "2.prems"(2) append_Nil2 list.size(3) list_conc old.prod.exhaust root_order.simps(2) snoc_eq_iff_butlast zero_less_iff_neq_zero) thenhave IH: "leaves (del k x t) = del_list x (leaves t) ∧ aligned lsep (del k x t) u" using"2.IH"(1)[OF list_split[symmetric] Nil, of lsep u] by (metis (no_types, lifting) "2.prems"(1) "2.prems"(2) "2.prems"(3) "2.prems"(4) "2.prems"(5) "2.prems"(7) ‹ls = ls' @ [(lsub, lsep)]› align_last aligned_sorted_separators bal.simps(2) list_conc list_split local.Nil order_impl_root_order root_order.simps(2) self_append_conv sorted_cons sorted_leaves_induct_last sorted_snoc split_set.split_req(2) split_set_axioms) have"leaves (del k x (Node ts t)) = leaves (rebalance_last_tree k ts (del k x t))" using list_split Nil list_conc by auto alsohave"… = leaves_list ts @ leaves (del k x t)" proof - obtain ts' sub sep where ts_split: "ts = ts' @ [(sub, sep)]" using‹ls = ls' @ [(lsub, lsep)]› list_conc local.Nil by blast thenhave"height sub = height t" using"2.prems"(3) by auto moreoverhave"height t = height (del k x t)" by (metis "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) del_height order_impl_root_order root_order.simps(2)) ultimatelyshow ?thesis using rebalance_last_tree_inorder using ts_split by auto qed alsohave"… = leaves_list ts @ del_list x (leaves t)" using IH by blast alsohave"… = del_list x (leaves (Node ts t))" by (metis "2.prems"(4) "2.prems"(5) aligned_imp_Laligned append_self_conv2 concat.simps(1) list.simps(8) list_conc list_split local.Nil self_append_conv split_set.del_list_split split_set_axioms) finallyhave0: "leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" . moreoverhave"aligned l (del k x (Node ts t)) u" proof - have"aligned l (Node ls (del k x t)) u" using IH list_conc Nil "2.prems" ls_split using aligned_subst_last by (metis self_append_conv) moreoverhave"sorted_less (leaves (Node ls (del k x t)))" using"2.prems"(4) ‹leaves_list ts @ del_list x (leaves t) = del_list x (leaves (Node ts t))›‹leaves_list ts @ leaves (del k x t) = leaves_list ts @ del_list x (leaves t)› list_conc local.Nil sorted_del_list by auto ultimatelyhave"aligned l (rebalance_last_tree k ls (del k x t)) u" using rebalance_last_tree_aligned by (metis (no_types, lifting) "2.prems"(1) "2.prems"(2) "2.prems"(3) UnCI bal.simps(2) del_height list.set_intros(1) list_conc ls_split order_impl_root_order root_order.simps(2) set_append some_child_sub(1)) thenshow ?thesis using list_split ls_split "2.prems" Nil by simp qed ultimatelyshow ?thesis by simp next case (Cons h rs) thenobtain sub sep where h_split: "h = (sub,sep)" by (cases h) thenhave node_sorted_split: "sorted_less (leaves (Node (ls@(sub,sep)#rs) t))" "root_order k (Node (ls@(sub,sep)#rs) t)" "bal (Node (ls@(sub,sep)#rs) t)" using"2.prems" h_split list_conc Cons by blast+
{ assume IH: "leaves (del k x sub) = del_list x (leaves sub)" have"leaves (del k x (Node ts t)) = leaves (rebalance_middle_tree k ls (del k x sub) sep rs t)" using Cons list_split h_split "2.prems" by auto alsohave"… = leaves (Node (ls@(del k x sub, sep)#rs) t)" using rebalance_middle_tree_inorder[of t "del k x sub" rs] by (smt (verit) "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) bal_sub_height del_height h_split list_split local.Cons node_sorted_split(3) order_impl_root_order rebalance_middle_tree_inorder root_order.simps(2) some_child_sub(1) split_set(1)) alsohave"… = leaves_list ls @ leaves (del k x sub) @ leaves_list rs @ leaves t" by auto alsohave"… = leaves_list ls @ del_list x (leaves sub @ leaves_list rs @ leaves t)" using del_list_split_right_aligned[of l ts t u x ls sub sep rs] using list_split Cons "2.prems"(4,5) h_split IH list_conc by auto alsohave"… = del_list x (leaves_list ls @ leaves sub @ leaves_list rs @ leaves t)" using del_list_split_aligned[of l ts t u x ls "(sub,sep)#rs"] using list_split Cons "2.prems"(4,5) h_split IH list_conc by auto finallyhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using list_conc Cons h_split by auto
} thenshow ?thesis proof (cases ls) case Nil thenhave IH: "leaves (del k x sub) = del_list x (leaves sub) ∧ aligned l (del k x sub) sep" using"2.IH"(2)[OF list_split[symmetric] Cons h_split[symmetric], of l sep] by (metis "2.prems"(1) "2.prems"(2) "2.prems"(5) "2.prems"(6) aligned.simps(2) aligned_sorted_separators append_self_conv2 bal.simps(2) h_split inbetween.simps(2) list.set_intros(1) list_conc list_split local.Cons local.Nil node_sorted_split(1) node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) sorted_cons sorted_leaves_induct_subtree sorted_snoc split_set.split_req(3) split_set_axioms) thenhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using‹leaves (del k x sub) = del_list x (leaves sub) ==> leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast thenhave"sorted_less (leaves (del k x (Node ts t)))" using"2.prems"(4) sorted_del_list by auto thenhave sorted_leaves: "sorted_less (leaves (Node (ls@(del k x sub, sep)#rs) t))" using list_split Cons h_split using rebalance_middle_tree_inorder[of t "del k x sub" rs k ls sep] using"2.prems"(4) "2.prems"(5) IH ‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))› del_list_split_aligned del_list_split_right_aligned by auto from IH have"aligned l (del k x (Node ts t)) u" proof - have"aligned l (Node (ls@(del k x sub, sep)#rs) t) u" using"2.prems"(5) IH h_split list_conc local.Cons local.Nil by auto thenhave"aligned l (rebalance_middle_tree k ls (del k x sub) sep rs t) u" using rebalance_middle_tree_aligned sorted_leaves by (smt (verit, best) "2.prems"(1) "2.prems"(2) "2.prems"(3) append_self_conv2 bal.simps(2) bal_sub_height del_height h_split list.set_intros(1) list_conc local.Cons local.Nil order_impl_root_order root_order.simps(2) some_child_sub(1)) thenshow ?thesis using list_split Cons h_split by auto qed thenshow ?thesis using‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast next case _: (Cons a list) thenobtain ls' lsub lsep where l_split: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep sub sep" using"2.prems"(5) align_last aligned_split_left h_split list_conc local.Cons by blast thenhave IH: "leaves (del k x sub) = del_list x (leaves sub) ∧ aligned lsep (del k x sub) sep" using"2.IH"(2)[OF list_split[symmetric] Cons h_split[symmetric], of lsep sep] by (metis "2.prems"(1) "2.prems"(2) "2.prems"(5) aligned_sorted_separators bal.simps(2) bal_split_left(1) h_split l_split list_split local.Cons node_sorted_split(1) node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) sorted_cons sorted_leaves_induct_subtree sorted_snoc split_set.split_req(2) split_set.split_req(3) split_set_axioms split_set(1)) thenhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using‹leaves (del k x sub) = del_list x (leaves sub) ==> leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast thenhave"sorted_less (leaves (del k x (Node ts t)))" using"2.prems"(4) sorted_del_list by auto thenhave sorted_leaves: "sorted_less (leaves (Node (ls@(del k x sub, sep)#rs) t))" using list_split Cons h_split using rebalance_middle_tree_inorder[of t "del k x sub" rs k ls sep] using"2.prems"(4) "2.prems"(5) IH ‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))› del_list_split_aligned del_list_split_right_aligned by auto from IH have"aligned l (del k x (Node ts t)) u" proof - have"aligned l (Node (ls@(del k x sub, sep)#rs) t) u" using"2.prems"(5) IH h_split list_conc local.Cons l_split using aligned_subst by fastforce thenhave"aligned l (rebalance_middle_tree k ls (del k x sub) sep rs t) u" using rebalance_middle_tree_aligned sorted_leaves by (smt (verit, best) "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) bal_sub_height del_height h_split list_split local.Cons node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) split_set(1)) thenshow ?thesis using list_split Cons h_split by auto qed thenshow ?thesis using‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast qed qed qed
lemma del_Linorder: assumes"k > 0" and"root_order k t" and"bal t" and"sorted_less (leaves t)" and"Laligned t u" and"x ≤ u" shows"leaves (del k x t) = del_list x (leaves t) ∧ Laligned (del k x t) u" using assms proof (induction k x t arbitrary: u rule: del.induct) case (1 k x xs) thenhave"leaves (del k x (Leaf xs)) = del_list x (leaves (Leaf xs))" by (simp add: insert_list_req) moreoverhave"Laligned (del k x (Leaf xs)) u" proof - have"∀x ∈ set xs - {x}. x ≤ u" using"1.prems"(5) by auto thenshow ?thesis using set_del_list insert_list_req by (metis "1"(4) Laligned.simps(1) del.simps(1) leaves.simps(1)) qed ultimatelyshow ?case by simp next case (2 k x ts t u) thenobtain ls rs where list_split: "split ts x = (ls, rs)" by (meson surj_pair) thenhave list_conc: "ts = ls @ rs" using split_set.split_conc split_set_axioms by blast show ?case proof (cases rs) case Nil thenobtain ls' lsub lsep where ls_split: "ls = ls' @ [(lsub,lsep)]" by (metis "2.prems"(2) append_Nil2 list.size(3) list_conc old.prod.exhaust root_order.simps(2) snoc_eq_iff_butlast zero_less_iff_neq_zero) thenhave IH: "leaves (del k x t) = del_list x (leaves t) ∧ aligned lsep (del k x t) u" by (metis (no_types, lifting) "2.prems"(1) "2.prems"(2) "2.prems"(3) "2.prems"(4) "2.prems"(5) "2.prems"(6) Lalign_last Laligned_sorted_separators bal.simps(2) del_inorder list_conc list_split local.Nil order_impl_root_order root_order.simps(2) self_append_conv sorted_leaves_induct_last sorted_snoc split_set.split_req(2) split_set_axioms) have"leaves (del k x (Node ts t)) = leaves (rebalance_last_tree k ts (del k x t))" using list_split Nil list_conc by auto alsohave"… = leaves_list ts @ leaves (del k x t)" proof - obtain ts' sub sep where ts_split: "ts = ts' @ [(sub, sep)]" using‹ls = ls' @ [(lsub, lsep)]› list_conc local.Nil by blast thenhave"height sub = height t" using"2.prems"(3) by auto moreoverhave"height t = height (del k x t)" by (metis "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) del_height order_impl_root_order root_order.simps(2)) ultimatelyshow ?thesis using rebalance_last_tree_inorder using ts_split by auto qed alsohave"… = leaves_list ts @ del_list x (leaves t)" using IH by blast alsohave"… = del_list x (leaves (Node ts t))" by (metis "2.prems"(4) "2.prems"(5) append_self_conv2 concat.simps(1) list.simps(8) list_conc list_split local.Nil self_append_conv split_set.del_list_split split_set_axioms) finallyhave0: "leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" . moreoverhave"Laligned (del k x (Node ts t)) u" proof - have"Laligned (Node ls (del k x t)) u" using IH list_conc Nil "2.prems" ls_split by (metis Laligned_subst_last self_append_conv) moreoverhave"sorted_less (leaves (Node ls (del k x t)))" using"2.prems"(4) ‹leaves_list ts @ del_list x (leaves t) = del_list x (leaves (Node ts t))›‹leaves_list ts @ leaves (del k x t) = leaves_list ts @ del_list x (leaves t)› list_conc local.Nil sorted_del_list by auto ultimatelyhave"Laligned (rebalance_last_tree k ls (del k x t)) u" using rebalance_last_tree_Laligned by (metis (no_types, lifting) "2.prems"(1) "2.prems"(2) "2.prems"(3) UnCI bal.simps(2) del_height list.set_intros(1) list_conc ls_split order_impl_root_order root_order.simps(2) set_append some_child_sub(1)) thenshow ?thesis using list_split ls_split "2.prems" Nil by simp qed ultimatelyshow ?thesis by simp next case (Cons h rs) thenobtain sub sep where h_split: "h = (sub,sep)" by (cases h) thenhave node_sorted_split: "sorted_less (leaves (Node (ls@(sub,sep)#rs) t))" "root_order k (Node (ls@(sub,sep)#rs) t)" "bal (Node (ls@(sub,sep)#rs) t)" using"2.prems" h_split list_conc Cons by blast+
{ assume IH: "leaves (del k x sub) = del_list x (leaves sub)" have"leaves (del k x (Node ts t)) = leaves (rebalance_middle_tree k ls (del k x sub) sep rs t)" using Cons list_split h_split "2.prems" by auto alsohave"… = leaves (Node (ls@(del k x sub, sep)#rs) t)" using rebalance_middle_tree_inorder[of t "del k x sub" rs] by (smt (verit) "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) bal_sub_height del_height h_split list_split local.Cons node_sorted_split(3) order_impl_root_order rebalance_middle_tree_inorder root_order.simps(2) some_child_sub(1) split_set(1)) alsohave"… = leaves_list ls @ leaves (del k x sub) @ leaves_list rs @ leaves t" by auto alsohave"… = leaves_list ls @ del_list x (leaves sub @ leaves_list rs @ leaves t)" using del_list_split_right[of ts t u x ls sub sep rs] using list_split Cons "2.prems"(4,5) h_split IH list_conc by auto alsohave"… = del_list x (leaves_list ls @ leaves sub @ leaves_list rs @ leaves t)" using del_list_split[of ts t u x ls "(sub,sep)#rs"] using list_split Cons "2.prems"(4,5) h_split IH list_conc by auto finallyhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using list_conc Cons h_split by auto
} thenshow ?thesis proof (cases ls) case Nil thenhave IH: "leaves (del k x sub) = del_list x (leaves sub) ∧ Laligned (del k x sub) sep" by (smt (verit, ccfv_threshold) "2.IH"(2) "2.prems"(1) "2.prems"(2) "2.prems"(5) Laligned_nonempty_Node Laligned_sorted_separators append_self_conv2 bal.simps(2) h_split list.set_intros(1) list_conc list_split local.Cons node_sorted_split(1) node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) sorted_leaves_induct_subtree sorted_wrt_append split_set.split_req(3) split_set_axioms) thenhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using‹leaves (del k x sub) = del_list x (leaves sub) ==> leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast thenhave"sorted_less (leaves (del k x (Node ts t)))" using"2.prems"(4) sorted_del_list by auto thenhave sorted_leaves: "sorted_less (leaves (Node (ls@(del k x sub, sep)#rs) t))" using list_split Cons h_split using rebalance_middle_tree_inorder[of t "del k x sub" rs k ls sep] using"2.prems"(4) "2.prems"(5) IH ‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))› del_list_split del_list_split_right by auto from IH have"Laligned (del k x (Node ts t)) u" proof - have"Laligned (Node (ls@(del k x sub, sep)#rs) t) u" using"2.prems"(5) IH h_split list_conc local.Cons local.Nil by auto thenhave"Laligned (rebalance_middle_tree k ls (del k x sub) sep rs t) u" using rebalance_middle_tree_Laligned sorted_leaves by (smt (verit, best) "2.prems"(1) "2.prems"(2) "2.prems"(3) append_self_conv2 bal.simps(2) bal_sub_height del_height h_split list.set_intros(1) list_conc local.Cons local.Nil order_impl_root_order root_order.simps(2) some_child_sub(1)) thenshow ?thesis using list_split Cons h_split by auto qed thenshow ?thesis using‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast next case _: (Cons a list) thenobtain ls' lsub lsep where l_split: "ls = ls'@[(lsub,lsep)]" by (metis list.discI old.prod.exhaust snoc_eq_iff_butlast) thenhave"aligned lsep sub sep" using"2.prems"(5) Lalign_last Laligned_split_left h_split list_conc local.Cons by blast thenhave IH: "leaves (del k x sub) = del_list x (leaves sub) ∧ aligned lsep (del k x sub) sep" by (metis "2.prems"(1) "2.prems"(2) "2.prems"(5) Laligned_sorted_separators bal.simps(2) bal_split_left(1) del_inorder h_split l_split list_split local.Cons node_sorted_split(1) node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) sorted_leaves_induct_subtree sorted_snoc split_set.split_req(2) split_set.split_req(3) split_set_axioms split_set(1)) thenhave"leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))" using‹leaves (del k x sub) = del_list x (leaves sub) ==> leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast thenhave"sorted_less (leaves (del k x (Node ts t)))" using"2.prems"(4) sorted_del_list by auto thenhave sorted_leaves: "sorted_less (leaves (Node (ls@(del k x sub, sep)#rs) t))" using list_split Cons h_split using rebalance_middle_tree_inorder[of t "del k x sub" rs k ls sep] using"2.prems"(4) "2.prems"(5) IH ‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))› del_list_split del_list_split_right by auto from IH have"Laligned (del k x (Node ts t)) u" proof - have"Laligned (Node (ls@(del k x sub, sep)#rs) t) u" using"2.prems"(5) IH h_split list_conc local.Cons l_split using Laligned_subst by fastforce thenhave"Laligned (rebalance_middle_tree k ls (del k x sub) sep rs t) u" using rebalance_middle_tree_Laligned sorted_leaves by (smt (verit, best) "2.prems"(1) "2.prems"(2) "2.prems"(3) bal.simps(2) bal_sub_height del_height h_split list_split local.Cons node_sorted_split(3) order_impl_root_order root_order.simps(2) some_child_sub(1) split_set(1)) thenshow ?thesis using list_split Cons h_split by auto qed thenshow ?thesis using‹leaves (del k x (Node ts t)) = del_list x (leaves (Node ts t))›by blast qed qed qed
lemma reduce_root_Laligned: "Laligned (reduce_root t) u = Laligned t u" apply(cases t) apply (auto split!: list.splits) done
lemma delete_order: "[k > 0; bal t; root_order k t; sorted_less (leaves t)]==> root_order k (delete k x t)" using del_order by (simp add: reduce_root_order)
lemma delete_bal: "[k > 0; bal t; root_order k t]==> bal (delete k x t)" using del_bal by (simp add: reduce_root_bal)
lemma delete_Linorder: assumes"k > 0""root_order k t""sorted_less (leaves t)""Laligned t u""bal t""x ≤u" shows"leaves (delete k x t) = del_list x (leaves t)" and"Laligned (delete k x t) u" using reduce_root_Laligned[of "del k x t" u] reduce_root_inorder[of "del k x t"] using del_Linorder[of k t u x] using assms by simp_all
corollary delete_Linorder_top: assumes"k > 0""root_order k t""sorted_less (leaves t)""Laligned t top""bal t" shows"leaves (delete k x t) = del_list x (leaves t)" and"Laligned (delete k x t) top" using assms delete_Linorder top_greatest by simp_all
(* TODO (opt) runtime wrt runtime of split *)
(* we are interested in a) number of comparisons b) number of fetches c) number of writes *) (* a) is dependent on t_split, the remainder is not (we assume the number of fetches and writes
for split fun is 0 *)
(* TODO simpler induction schemes /less boilerplate isabelle/src/HOL/ex/Induction_Schema *)
subsection"Set specification by inorder"
fun invar_leaves where"invar_leaves k t = ( bal t ∧ root_order k t ∧ Laligned t top )"
interpretation S_ordered: Set_by_Ordered where
empty = empty_bplustree and
insert = "insert (Suc k)"and
delete = "delete (Suc k)"and
isin = "isin"and
inorder = "leaves"and
inv = "invar_leaves (Suc k)" proof (standard, goal_cases) case (2 s x) thenshow ?case using isin_set_Linorder_top by simp next case (3 s x) thenshow ?case using insert_Linorder_top by simp next case (4 s x) thenshow ?caseusing delete_Linorder_top by auto next case (6 s x) thenshow ?caseusing insert_order insert_bal insert_Linorder_top by auto next case (7 s x) thenshow ?caseusing delete_order delete_bal delete_Linorder_top by auto qed (simp add: empty_bplustree_def)+
(* if we remove this, it is not possible to remove the simp rules in subsequent contexts... *) declare nodei.simps[simp del]
end
(* copied from comment in List_Ins_Del *) lemma sorted_ConsD: "sorted_less (y # xs) ==> x ≤ y ==> x ∉ set xs" by (auto simp: sorted_Cons_iff)
lemma sorted_snocD: "sorted_less (xs @ [y]) ==> y ≤ x ==> x ∉ set xs" by (auto simp: sorted_snoc_iff)
lemma isin_sorted_split_list: assumes"sorted_less xs" and"split_list xs x = (ls, rs)" shows"(x ∈ set xs) = (x ∈ set rs)" proof (cases ls) case Nil thenhave"xs = rs" using assms by (auto dest!: split_list_conc) thenshow ?thesis by simp next case Cons thenobtain ls' sep where ls_tail_split: "ls = ls' @ [sep]" by (metis list.simps(3) rev_exhaust) thenhave x_sm_sep: "sep < x" using split_list_req(2)[of xs x ls' sep rs] using assms sorted_cons sorted_snoc by blast moreoverhave"xs = ls@rs" using assms split_list_conc by simp ultimatelyshow ?thesis using isin_sorted[of ls' sep rs] using assms ls_tail_split by auto qed
lemma isin_sorted_split_list_right: assumes"split_list ts x = (ls, sep#rs)" and"sorted_less ts" shows"x ∈ set (sep#rs) = (x = sep)" proof (cases rs) case Nil thenshow ?thesis by simp next case (Cons sep' rs) from assms have"x < sep'" by (metis le_less less_trans list.set_intros(1) local.Cons sorted_Cons_iff sorted_wrt_append split_list_conc split_list_sorted(2)) moreoverhave"ts = ls@sep#sep'#rs" using split_list_conc[OF assms(1)] Cons by auto moreoverhave"sorted_less (sep#sep'#rs)" using Cons assms calculation(2) sorted_wrt_append by blast ultimatelyshow ?thesis using isin_sorted[of "[sep]" sep' rs x] Cons by simp qed
theorem isin_list_set: assumes"sorted_less xs" shows"isin_list x xs = (x ∈ set xs)" using assms using isin_sorted_split_list[of xs x] using isin_sorted_split_list_right[of xs x] by (auto split!: list.splits)
lemma insert_sorted_split_list: assumes"sorted_less xs" and"split_list xs x = (ls, rs)" shows"ins_list x xs = ls @ ins_list x rs" proof (cases ls) case Nil thenhave"xs = rs" using assms by (auto dest!: split_list_conc) thenshow ?thesis using Nil by simp next case Cons thenobtain ls' sep where ls_tail_split: "ls = ls' @ [sep]" by (metis list.simps(3) rev_exhaust) thenhave x_sm_sep: "sep < x" using split_list_req(2)[of xs x ls' sep rs] using assms sorted_cons sorted_snoc by blast moreoverhave"xs = ls@rs" using assms split_list_conc by simp ultimatelyshow ?thesis using ins_list_sorted[of ls' sep x rs] using assms ls_tail_split sorted_wrt_append[of "(<)" ls rs] by auto qed
lemma insert_sorted_split_list_right: assumes"split_list ts x = (ls, sep#rs)" and"sorted_less ts" and"x ≠ sep" shows"ins_list x (sep#rs) = (x#sep#rs)" proof - have"x < sep" by (meson assms(1) assms(2) assms(3) le_neq_trans split_list_sorted(2)) thenshow ?thesis using ins_list_sorted[of "[]" sep] using assms by auto qed
theorem insert_list_set: assumes"sorted_less xs" shows"insert_list x xs = ins_list x xs" using assms split_list_conc using insert_sorted_split_list[of xs x] using insert_sorted_split_list_right[of xs x] by (auto split!: list.splits prod.splits)
lemma delete_sorted_split_list: assumes"sorted_less xs" and"split_list xs x = (ls, rs)" shows"del_list x xs = ls @ del_list x rs" proof (cases ls) case Nil thenhave"xs = rs" using assms by (auto dest!: split_list_conc) thenshow ?thesis using Nil by simp next case Cons thenobtain ls' sep where ls_tail_split: "ls = ls' @ [sep]" by (metis list.simps(3) rev_exhaust) thenhave x_sm_sep: "sep < x" using split_list_req(2)[of xs x ls' sep rs] using assms sorted_cons sorted_snoc by blast moreoverhave"xs = ls@rs" using assms split_list_conc by simp ultimatelyshow ?thesis using del_list_sorted[of ls' sep rs] using assms ls_tail_split sorted_wrt_append[of "(<)" ls rs] by auto qed
lemma delete_sorted_split_list_right: assumes"split_list ts x = (ls, sep#rs)" and"sorted_less ts" and"x ≠ sep" shows"del_list x (sep#rs) = sep#rs" proof - have"sorted_less (sep#rs)" by (metis assms(1) assms(2) sorted_wrt_append split_list.split_list_conc split_list_axioms) moreoverhave"x < sep" by (meson assms(1) assms(2) assms(3) le_neq_trans split_list_sorted(2)) ultimatelyshow ?thesis using del_list_sorted[of "[]" sep rs x] by simp qed
theorem delete_list_set: assumes"sorted_less xs" shows"delete_list x xs = del_list x xs" using assms split_list_conc[of xs x] using delete_sorted_split_list[of xs x] using delete_sorted_split_list_right[of xs x] by (auto split!: list.splits prod.splits)
end
context split_full begin
sublocale split_set split isin_list insert_list delete_list using isin_list_set insert_list_set delete_list_set by unfold_locales auto
end
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.179 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.