lemma snd_map_help: "x ≤ length tsi ==> (∀j<x. snd (tsi ! j) = ((map snd tsi)!j))" "x < length tsi ==> snd (tsi!x) = ((map snd tsi)!x)" by auto
lemma split_ismeq: "((a::nat) ≤ b ∧ X) = ((a < b ∧ X) ∨ (a = b ∧ X))" by auto
lemma split_relation_map: "split_relation as (ls,rs) i ==> split_relation (map f as) (map f ls, map f rs) i" apply(induction as arbitrary: ls rs i) apply(auto simp add: split_relation_def take_map drop_Cons') apply(metis list.simps(9) take_map) done
lemma split_relation_access: "[split_relation as (ls,rs) i; rs = r#rrs]==> as!i = r" by (simp add: split_relation_alt)
lemma index_to_elem_all: "(∀j<length xs. P (xs!j)) = (∀x ∈ set xs. P x)" by (simp add: all_set_conv_nth)
lemma index_to_elem: "n < length xs ==> (∀j<n. P (xs!j)) = (∀x ∈ set (take n xs). P x)" by (simp add: all_set_conv_nth) (* ----------------- *)
definition split_half :: "('a::heap × 'b::{heap}) pfarray ==> nat Heap" where "split_half a ≡ do { l ← pfa_length a; return (l div 2) }"
lemma split_half_rule[sep_heap_rules]: "< is_pfa c tsi a * list_assn R ts tsi> split_half a <λi. is_pfa c tsi a * list_assn R ts tsi * ↑(i = length ts div 2 ∧ split_relation ts (BTree_Set.split_half ts) i)>" unfolding split_half_def split_relation_def apply(rule hoare_triple_preI) apply(sep_auto dest!: list_assn_len mod_starD) done
subsection"The imperative split locale"
text"This locale extends the abstract split locale, assuming that we are provided with an imperative program that refines the abstract split function."
locale imp_split = abs_split: BTree_Set.split split for split:: "('a btree × 'a::{heap,default,linorder}) list ==> 'a ==> ('a btree × 'a) list × ('a btree × 'a) list" + fixes imp_split:: "('a btnode ref option × 'a::{heap,default,linorder}) pfarray ==> 'a ==> nat Heap" assumes imp_split_rule [sep_heap_rules]:"sorted_less (separators ts) ==> <is_pfa c tsi (a,n) * blist_assn k ts tsi> imp_split (a,n) p <λi. is_pfa c tsi (a,n) * blist_assn k ts tsi * ↑(split_relation ts (split ts p) i)>t" begin
subsection"Membership"
partial_function (heap) isin :: "'a btnode ref option ==> 'a ==> bool Heap" where "isin p x = (case p of None ==> return False | (Some a) ==> do { node ← !a; i ← imp_split (kvs node) x; tsl ← pfa_length (kvs node); if i < tsl then do { s ← pfa_get (kvs node) i; let (sub,sep) = s in if x = sep then return True else isin sub x } else isin (last node) x } )"
fun btupi_assn where "btupi_assn k (abs_split.Ti l) (Ti li) = btree_assn k l li" | "btupi_assn k (abs_split.Upi l a r) (Upi li ai ri) = btree_assn k l li * id_assn a ai * btree_assn k r ri" | "btupi_assn _ _ _ = false"
definition nodei :: "nat ==> ('a btnode ref option × 'a) pfarray ==> 'a btnode ref option ==> 'a btupi Heap"where "nodei k a ti ≡ do { n ← pfa_length a; if n ≤ 2*k then do { a' ← pfa_shrink_cap (2*k) a; l ← ref (Btnode a' ti); return (Ti (Some l)) } else do { b ← (pfa_empty (2*k) :: ('a btnode ref option × 'a) pfarray Heap); i ← split_half a; m ← pfa_get a i; b' ← pfa_drop a (i+1) b; a' ← pfa_shrink i a; a'' ← pfa_shrink_cap (2*k) a'; let (sub,sep) = m in do { l ← ref (Btnode a'' sub); r ← ref (Btnode b' ti); return (Upi (Some l) sep (Some r)) } } }"
partial_function (heap) ins :: "nat ==> 'a ==> 'a btnode ref option ==> 'a btupi Heap" where "ins k x apo = (case apo of None ==> return (Upi None x None) | (Some ap) ==> do { a ← !ap; i ← imp_split (kvs a) x; tsl ← pfa_length (kvs a); if i < tsl then do { s ← pfa_get (kvs a) i; let (sub,sep) = s in if sep = x then return (Ti apo) else do { r ← ins k x sub; case r of (Ti lp) ==> do { pfa_set (kvs a) i (lp,sep); return (Ti apo) } | (Upi lp x' rp) ==> do { pfa_set (kvs a) i (rp,sep); if tsl < 2*k then do { kvs' ← pfa_insert (kvs a) i (lp,x'); ap := (Btnode kvs' (last a)); return (Ti apo) } else do { kvs' ← pfa_insert_grow (kvs a) i (lp,x'); nodei k kvs' (last a) } } } } else do { r ← ins k x (last a); case r of (Ti lp) ==> do { ap := (Btnode (kvs a) lp); return (Ti apo) } | (Upi lp x' rp) ==> if tsl < 2*k then do { kvs' ← pfa_append (kvs a) (lp,x'); ap := (Btnode kvs' rp); return (Ti apo) } else do { kvs' ← pfa_append_grow' (kvs a) (lp,x'); nodei k kvs' rp } } } )"
(*fun tree\<^sub>i::"'a up\<^sub>i \<Rightarrow> 'a btree" where "tree\<^sub>i(T\<^sub>isub)=sub"| "tree\<^sub>i(Up\<^sub>ilar)=(Node[(l,a)]r)"
definition insert :: "nat ==> ('a::{heap,default,linorder}) ==> 'a btnode ref option ==> 'a btnode ref option Heap"where "insert ≡ λk x ti. do { ti' ← ins k x ti; case ti' of Ti sub ==> return sub | Upi l a r ==> do { kvs ← pfa_init (2*k) (l,a) 1; t' ← ref (Btnode kvs r); return (Some t') } }"
subsection"Deletion"
(* rebalance middle tree gets a list of trees, an index pointing to
the position of sub/sep and a last tree *) definition rebalance_middle_tree:: "nat ==> (('a::{default,heap,linorder}) btnode ref option × 'a) pfarray ==> nat ==> 'a btnode ref option ==> 'a btnode Heap" where "rebalance_middle_tree ≡ λ k tsi i r_ti. ( case r_ti of None ==> do { (r_sub,sep) ← pfa_get tsi i; case r_sub of None ==> return (Btnode tsi r_ti) } | Some p_t ==> do { (r_sub,sep) ← pfa_get tsi i; case r_sub of (Some p_sub) ==> do { ti ← !p_t; sub ← !p_sub; l_sub ← pfa_length (kvs sub); l_tts ← pfa_length (kvs ti); if l_sub ≥ k ∧ l_tts ≥ k then do { return (Btnode tsi r_ti) } else do { l_tsi ← pfa_length tsi; if i+1 = l_tsi then do { mts' ← pfa_append_extend_grow (kvs sub) (last sub,sep) (kvs ti); res_nodei← nodei k mts' (last ti); case res_nodei of Ti u ==> do { tsi' ← pfa_shrink i tsi; return (Btnode tsi' u) } | Upi l a r ==> do { tsi' ← pfa_set tsi i (l,a); return (Btnode tsi' r) } } else do { (r_rsub,rsep) ← pfa_get tsi (i+1); case r_rsub of Some p_rsub ==> do { rsub ← !p_rsub; mts' ← pfa_append_extend_grow (kvs sub) (last sub,sep) (kvs rsub); res_nodei← nodei k mts' (last rsub); case res_nodei of Ti u ==> do { tsi' ← pfa_set tsi i (u,rsep); tsi'' ← pfa_delete tsi' (i+1); return (Btnode tsi'' r_ti) } | Upi l a r ==> do { tsi' ← pfa_set tsi i (l,a); tsi'' ← pfa_set tsi' (i+1) (r,rsep); return (Btnode tsi'' r_ti) } } } } } })
"
definition rebalance_last_tree:: "nat ==> (('a::{default,heap,linorder}) btnode ref option × 'a) pfarray ==> 'a btnode ref option ==> 'a btnode Heap" where "rebalance_last_tree ≡ λk tsi ti. do { l_tsi ← pfa_length tsi; rebalance_middle_tree k tsi (l_tsi-1) ti }"
subsection"Refinement of the abstract B-tree operations"
lemma"sorted_less (inorder t) ==> <btree_assn k t ti> isin ti x <λr. btree_assn k t ti * ↑(abs_split.isin t x = r)>t" proof(induction t x arbitrary: ti rule: abs_split.isin.induct) case (1 x) thenshow ?case apply(subst isin.simps) apply (cases ti) apply (auto simp add: return_cons_rule) done next case (2 ts t x) thenobtain ls rs where list_split[simp]: "split ts x = (ls,rs)" by (cases "split ts x") thenshow ?case proof (cases rs) (* NOTE: induction condition trivial here *) case [simp]: Nil show ?thesis apply(subst isin.simps) apply(sep_auto) using"2.prems" sorted_inorder_separators apply blast apply(auto simp add: split_relation_def dest!: sym[of "[]"] mod_starD list_assn_len)[] apply(rule hoare_triple_preI) apply(auto simp add: split_relation_def dest!: sym[of "[]"] mod_starD list_assn_len)[] using2(3) apply(sep_auto heap: "2.IH"(1)[of ls "[]"] simp add: sorted_wrt_append) done next case [simp]: (Cons h rrs) obtain sub sep where h_split[simp]: "h = (sub,sep)" by (cases h) show ?thesis proof (cases "sep = x") (* NOTE: no induction required here, only vacuous counter cases generated *) case [simp]: True thenshow ?thesis apply(simp split: list.splits prod.splits) apply(subst isin.simps) using"2.prems" sorted_inorder_separators apply(sep_auto) apply(rule hoare_triple_preI) apply(auto simp add: split_relation_alt list_assn_append_Cons_left dest!: mod_starD list_assn_len)[] apply(rule hoare_triple_preI) apply(auto simp add: split_relation_def dest!: sym[of "[]"] mod_starD list_assn_len)[] done next case [simp]: False show ?thesis apply(simp split: list.splits prod.splits) apply safe using False apply simp apply(subst isin.simps) using"2.prems" sorted_inorder_separators apply(sep_auto) (*eliminate vacuous case*) apply(auto simp add: split_relation_alt list_assn_append_Cons_left dest!: mod_starD list_assn_len)[] (* simplify towards induction step *) apply(auto simp add: split_relation_alt list_assn_append_Cons_left dest!: mod_starD list_assn_len)[]
(* NOTE show that z = (suba, sepa) *) apply(rule norm_pre_ex_rule)+ apply(rule hoare_triple_preI)
subgoal for p tsi n ti xsi suba sepa zs1 z zs2 _ apply(subgoal_tac "z = (suba, sepa)", simp) using2(3) apply(sep_auto
heap:"2.IH"(2)[of ls rs h rrs sub sep]
simp add: sorted_wrt_append) using list_split Cons h_split apply simp_all (* proof that previous assumptions hold later *) apply(rule P_imp_Q_implies_P) apply(rule ent_ex_postI[where x="(tsi,n)"]) apply(rule ent_ex_postI[where x="ti"]) apply(rule ent_ex_postI[where x="(zs1 @ (suba, sepa) # zs2)"]) apply(rule ent_ex_postI[where x="zs1"]) apply(rule ent_ex_postI[where x="z"]) apply(rule ent_ex_postI[where x="zs2"]) apply sep_auto (* prove subgoal_tac assumption *) apply (metis (no_types, lifting) list_assn_aux_ineq_len list_assn_len nth_append_length star_false_left star_false_right) done (* eliminate last vacuous case *) apply(rule hoare_triple_preI) apply(auto simp add: split_relation_def dest!: mod_starD list_assn_len)[] done qed qed qed
declare abs_split.nodei.simps [simp add]
lemma nodei_rule: assumes c_cap: "2*k ≤ c""c ≤ 4*k+1" shows"<is_pfa c tsi (a,n) * list_assn ((btree_assn k) ×a id_assn) ts tsi * btree_assn k t ti> nodei k (a,n) ti <λr. btupi_assn k (abs_split.nodei k ts t) r >t" proof (cases "length ts ≤ 2 * k") case [simp]: True thenshow ?thesis apply(subst nodei_def) apply(rule hoare_triple_preI) apply(sep_auto dest!: mod_starD list_assn_len) apply(sep_auto simp add: is_pfa_def)[] using c_cap apply(sep_auto simp add: is_pfa_def)[] apply(sep_auto dest!: mod_starD list_assn_len)[] using True apply(sep_auto dest!: mod_starD list_assn_len) done next note max.absorb1 [simp del] max.absorb2 [simp del] max.absorb3 [simp del] max.absorb4 [simp del] note min.absorb1 [simp del] min.absorb2 [simp del] min.absorb3 [simp del] min.absorb4 [simp del] case [simp]: False thenobtain ls sub sep rs where
split_half_eq: "BTree_Set.split_half ts = (ls,(sub,sep)#rs)" using abs_split.nodei_casesby blast thenshow ?thesis apply(subst nodei_def) apply(rule hoare_triple_preI) apply(sep_auto dest!: mod_starD list_assn_len) apply(sep_auto simp add: split_relation_alt split_relation_length is_pfa_def dest!: mod_starD list_assn_len) using False apply(sep_auto simp add: split_relation_alt ) using False apply(sep_auto simp add: is_pfa_def)[] apply(sep_auto)[] apply(sep_auto simp add: is_pfa_def split_relation_alt)[] using c_cap apply(sep_auto simp add: is_pfa_def)[] apply(sep_auto)[] using c_cap apply(sep_auto simp add: is_pfa_def)[] using c_cap apply(simp) apply(vcg) apply(simp) apply(rule impI)
subgoal for _ _ _ _ rsa subi ba rn lsi al ar _ thm ent_ex_postI thm ent_ex_postI[where x="take (length tsi div 2) tsi"] (* instantiate right hand side *) apply(rule ent_ex_postI[where x="(rsa,rn)"]) apply(rule ent_ex_postI[where x="ti"]) apply(rule ent_ex_postI[where x="(drop (Suc (length tsi div 2)) tsi)"]) apply(rule ent_ex_postI[where x="lsi"]) apply(rule ent_ex_postI[where x="subi"]) apply(rule ent_ex_postI[where x="take (length tsi div 2) tsi"]) (* introduce equality between equality of split tsi/ts and original lists *) apply(simp add: split_relation_alt) apply(subgoal_tac "tsi = take (length tsi div 2) tsi @ (subi, ba) # drop (Suc (length tsi div 2)) tsi") apply(rule back_subst[where a="blist_assn k ts (take (length tsi div 2) tsi @ (subi, ba) # (drop (Suc (length tsi div 2)) tsi))"and b="blist_assn k ts tsi"]) apply(rule back_subst[where a="blist_assn k (take (length tsi div 2) ts @ (sub, sep) # rs)"and b="blist_assn k ts"]) apply(subst list_assn_aux_append_Cons) apply sep_auto apply sep_auto apply simp apply simp apply(rule back_subst[where a="tsi ! (length tsi div 2)"and b="(subi, ba)"]) apply(rule id_take_nth_drop) apply simp apply simp done done qed declare abs_split.nodei.simps [simp del]
lemma nodei_no_split: "length ts ≤ 2*k ==> abs_split.nodei k ts t = abs_split.Ti (Node ts t)" by (simp add: abs_split.nodei.simps)
lemma nodei_rule_app: "[2*k ≤ c; c ≤ 4*k+1]==> <is_pfa c (tsi' @ [(li, ai)]) (aa, al) * blist_assn k ls tsi' * btree_assn k l li * id_assn a ai * btree_assn k r ri> nodei k (aa, al) ri <btupi_assn k (abs_split.nodei k (ls @ [(l, a)]) r)>t" proof - note nodei_rule[of k c "(tsi' @ [(li, ai)])" aa al "(ls @ [(l, a)])" r ri] moreoverassume"2*k ≤ c""c ≤ 4*k+1" ultimatelyshow ?thesis by (simp add: mult.left_assoc) qed
lemma nodei_rule_ins2: "[2*k ≤ c; c ≤ 4*k+1; length ls = length lsi]==> <is_pfa c (lsi @ (li, ai) # (ri,a'i) # rsi) (aa, al) * blist_assn k ls lsi * btree_assn k l li * id_assn a ai * btree_assn k r ri * id_assn a' a'i * blist_assn k rs rsi * btree_assn k t ti> nodei k (aa, al) ti <btupi_assn k (abs_split.nodei k (ls @ (l, a) # (r,a') # rs) t)>t" proof - assume [simp]: "2*k ≤ c""c ≤ 4*k+1""length ls = length lsi" moreovernote nodei_rule[of k c "(lsi @ (li, ai) # (ri,a'i) # rsi)" aa al "(ls @ (l, a) # (r,a') # rs)" t ti] ultimatelyshow ?thesis by (simp add: mult.left_assoc list_assn_aux_append_Cons) qed
lemma ins_rule: "sorted_less (inorder t) ==> <btree_assn k t ti> ins k x ti <λr. btupi_assn k (abs_split.ins k x t) r>t" proof (induction k x t arbitrary: ti rule: abs_split.ins.induct) case (1 k x) thenshow ?case apply(subst ins.simps) apply (sep_auto simp add: pure_app_eq) done next case (2 k x ts t) obtain ls rrs where list_split: "split ts x = (ls,rrs)" by (cases "split ts x") have [simp]: "sorted_less (separators ts)" using"2.prems" sorted_inorder_separators by simp have [simp]: "sorted_less (inorder t)" using"2.prems" sorted_inorder_induct_last by simp show ?case proof (cases rrs) case Nil thenshow ?thesis proof (cases "abs_split.ins k x t") case (Ti a) thenshow ?thesis apply(subst ins.simps) apply(sep_auto)
subgoal for p tsil tsin tti using Nil list_split by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for p tsil tsin tti tsi' i tsin' _ sub sep apply(rule hoare_triple_preI) using Nil list_split by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for p tsil tsin tti tsi' thm"2.IH"(1)[of ls rrs tti] using Nil list_split Tiapply(sep_auto split!: list.splits simp add: split_relation_alt
heap add: "2.IH"(1)[of ls rrs tti])
subgoal for ai apply(cases ai) apply sep_auto apply sep_auto done done done next case (Upi l a r) thenshow ?thesis apply(subst ins.simps) apply(sep_auto)
subgoal for p tsil tsin tti using Nil list_split by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for p tsil tsin tti tsi' i tsin' _ sub sep using Nil list_split by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for p tsil tsin tti tsi' i tsin' thm"2.IH"(1)[of ls rrs tti] using Nil list_split Upiapply(sep_auto split!: list.splits
simp add: split_relation_alt
heap add: "2.IH"(1)[of ls rrs tti])
subgoal for ai apply(cases ai) apply sep_auto apply(rule hoare_triple_preI) apply(sep_auto) apply(auto dest!: mod_starD simp add: is_pfa_def)[] apply (sep_auto)
subgoal for li ai ri (* no split case *) apply(subgoal_tac "length (ls @ [(l,a)]) ≤ 2*k") apply(simp add: nodei_no_split) apply(rule ent_ex_postI[where x="(tsil,Suc tsin)"]) apply(rule ent_ex_postI[where x="ri"]) apply(rule ent_ex_postI[where x="tsi' @ [(li, ai)]"]) apply(sep_auto) apply (sep_auto dest!: mod_starD list_assn_len simp add: is_pfa_def) done (* split case*) apply(sep_auto heap add: nodei_rule_app) done done done qed next case (Cons a rs) obtain sub sep where a_split: "a = (sub,sep)" by (cases a) thenhave [simp]: "sorted_less (inorder sub)" using"2.prems" abs_split.split_axioms list_split Cons sorted_inorder_induct_subtree split_def by fastforce thenshow ?thesis proof(cases "x = sep") case True show ?thesis apply(subst ins.simps) apply(sep_auto)
subgoal for p tsil tsin tti tsi j subi using Cons list_split a_split True by sep_auto
subgoal for p tsil tsin tti tsi j _ _ subi sepi apply(rule hoare_triple_preI) using Cons list_split a_split True apply(subgoal_tac "sepi = sep") apply (sep_auto simp add: split_relation_alt) apply(sep_auto simp add: list_assn_prod_map dest!: mod_starD id_assn_list) by (metis length_map snd_conv snd_map_help(2) split_relation_access)
subgoal for p tsil tsin tti tsi j apply(rule hoare_triple_preI) using Cons list_split by (sep_auto simp add: split_relation_alt dest!: mod_starD list_assn_len) done next case False thenshow ?thesis proof (cases "abs_split.ins k x sub") case (Ti a') thenshow ?thesis apply(auto simp add: Cons list_split a_split False) using False apply simp apply(subst ins.simps) apply vcg apply auto apply(rule norm_pre_ex_rule)+ (* at this point, we want to introduce the split, and after that tease the
hoare triple assumptions out of the bracket, s.t. we don't split twice *) apply vcg apply sep_auto using list_split Cons apply(simp add: split_relation_alt list_assn_append_Cons_left) apply (rule impI) apply(rule norm_pre_ex_rule)+ apply(rule hoare_triple_preI) apply sep_auto (* discard wrong branch *)
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ suba apply(subgoal_tac "sepi = x") using list_split Cons a_split apply(auto dest!: mod_starD )[] apply(auto dest!: mod_starD list_assn_len)[] done (* actual induction branch *)
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ n z suba sepa apply (cases a, simp) apply(subgoal_tac "subi = suba", simp) using list_split a_split Ti False apply (vcg heap: 2) apply(auto split!: btupi.splits) (* careful progression for manual value insertion *) apply vcg apply simp apply vcg apply simp
subgoal for a'i q r apply(rule impI) apply(simp add: list_assn_append_Cons_left) apply(rule ent_ex_postI[where x="(tsil,tsin)"]) apply(rule ent_ex_postI[where x="ti"]) apply(rule ent_ex_postI[where x="(zs1 @ (a'i, sepi) # zs2)"]) apply(rule ent_ex_postI[where x="zs1"]) apply(rule ent_ex_postI[where x="(a'i,sep)"]) apply(rule ent_ex_postI[where x="zs2"]) apply sep_auto apply (simp add: pure_app_eq) apply(sep_auto dest!: mod_starD list_assn_len)[] done apply (metis list_assn_aux_ineq_len Pair_inject list_assn_len nth_append_length star_false_left star_false_right) done
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ suba apply(auto dest!: mod_starD list_assn_len)[] done done next case (Upi l w r) thenshow ?thesis apply(auto simp add: Cons list_split a_split False) using False apply simp apply(subst ins.simps) apply vcg apply auto apply(rule norm_pre_ex_rule)+ (* at this point, we want to introduce the split, and after that tease the
hoare triple assumptions out of the bracket, s.t. we don't split twice *) apply vcg apply sep_auto using list_split Cons apply(simp add: split_relation_alt list_assn_append_Cons_left) apply (rule impI) apply(rule norm_pre_ex_rule)+ apply(rule hoare_triple_preI) apply sep_auto (* discard wrong branch *)
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ suba apply(subgoal_tac "sepi = x") using list_split Cons a_split apply(auto dest!: mod_starD )[] apply(auto dest!: mod_starD list_assn_len)[] done (* actual induction branch *)
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ n z suba sepa apply(subgoal_tac "subi = suba", simp) thm2(2)[of ls rrs a rs sub sep] using list_split a_split Cons Upi False apply (sep_auto heap: 2(2)) apply(auto split!: btupi.splits) (* careful progression for manual value insertion *) apply vcg apply simp
subgoal for li wi ri u (* no split case *) apply (cases u,simp) apply (sep_auto dest!: mod_starD list_assn_len heap: pfa_insert_grow_rule) apply (simp add: is_pfa_def)[] apply (metis le_less_linear length_append length_take less_not_refl min.absorb2 trans_less_add1) apply(simp add: is_pfa_def) apply (metis add_Suc_right length_Cons length_append length_take min.absorb2) apply(sep_auto split: prod.splits dest!: mod_starD list_assn_len)[] (* no split case *) apply(subgoal_tac "length (ls @ [(l,w)]) ≤ 2*k") apply(simp add: nodei_no_split) apply(rule ent_ex_postI[where x="(tsil,Suc tsin)"]) apply(rule ent_ex_postI[where x="ti"]) apply(rule ent_ex_postI[where x="(zs1 @ (li, wi) # (ri, sep) # zs2)"]) apply(sep_auto dest!: mod_starD list_assn_len) apply (sep_auto dest!: mod_starD list_assn_len simp add: is_pfa_def) done apply vcg apply simp
subgoal for x21 x22 x23 u (* split case *) apply (cases u,simp) thm pfa_insert_grow_rule[where ?l="((zs1 @ (suba, sepi) # zs2)[length ls := (x23, sepa)])"] apply (sep_auto dest!: mod_starD list_assn_len heap: pfa_insert_grow_rule) apply (simp add: is_pfa_def)[] apply (metis le_less_linear length_append length_take less_not_refl min.absorb2 trans_less_add1) apply(auto split: prod.splits dest!: mod_starD list_assn_len)[]
apply (vcg heap: nodei_rule_ins2) apply simp apply simp apply simp apply sep_auto done apply(auto dest!: mod_starD list_assn_len)[] done
subgoal for p tsil tsin ti zs1 subi sepi zs2 _ _ suba apply(auto dest!: mod_starD list_assn_len)[] done done qed qed qed qed
text"The imperative insert refines the abstract insert."
lemma insert_rule: assumes"k > 0""sorted_less (inorder t)" shows"<btree_assn k t ti> insert k x ti <λr. btree_assn k (abs_split.insert k x t) r>t" unfolding insert_def apply(cases "abs_split.ins k x t") apply(sep_auto split!: btupi.splits heap: ins_rule[OF assms(2)]) using assms apply(vcg heap: ins_rule[OF assms(2)]) apply(simp split!: btupi.splits) apply(vcg) apply auto[] apply vcg apply auto[]
subgoal for l a r li ai ri tsa tsn ti apply(rule ent_ex_postI[where x="(tsa,tsn)"]) apply(rule ent_ex_postI[where x="ri"]) apply(rule ent_ex_postI[where x="[(li, ai)]"]) apply sep_auto done done
text"The \"pure\" resulting rule follows automatically." lemma insert_rule': shows"<btree_assn (Suc k) t ti * ↑(abs_split.invar_inorder (Suc k) t ∧ sorted_less (inorder t))> insert (Suc k) x ti <λri.∃Ar. btree_assn (Suc k) r ri * ↑(abs_split.invar_inorder (Suc k) r ∧ sorted_less (inorder r) ∧ inorder r = (ins_list x (inorder t)))>t" using abs_split.insert_bal abs_split.insert_order abs_split.insert_inorder by (sep_auto heap: insert_rule simp add: sorted_ins_list)
lemma list_update_length2 [simp]: "(xs @ x # y # ys)[Suc (length xs) := z] = (xs @ x # z # ys)" by (induct xs, auto)
lemma nodei_rule_ins: "[2*k ≤ c; c ≤ 4*k+1; length ls = length lsi]==> <is_pfa c (lsi @ (li, ai) # rsi) (aa, al) * blist_assn k ls lsi * btree_assn k l li * id_assn a ai * blist_assn k rs rsi * btree_assn k t ti> nodei k (aa, al) ti <btupi_assn k (abs_split.nodei k (ls @ (l, a) # rs) t)>t" proof - assume [simp]: "2*k ≤ c""c ≤ 4*k+1""length ls = length lsi" moreovernote nodei_rule[of k c "(lsi @ (li, ai) # rsi)" aa al "(ls @ (l, a) # rs)" t ti] ultimatelyshow ?thesis by (simp add: mult.left_assoc list_assn_aux_append_Cons) qed
lemma btupi_assn_T: "h ⊨ btupi_assn k (abs_split.nodei k ts t) (Ti x) ==> abs_split.nodei k ts t = abs_split.Ti (Node ts t)" apply(auto simp add: abs_split.nodei.simps dest!: mod_starD split!: list.splits) done
lemma btupi_assn_Up: "h ⊨ btupi_assn k (abs_split.nodei k ts t) (Upi l a r) ==> abs_split.nodei k ts t = ( case BTree_Set.split_half ts of (ls, (sub,sep)#rs) ==> abs_split.Upi (Node ls sub) sep (Node rs t))" apply(auto simp add: abs_split.nodei.simps dest!: mod_starD split!: list.splits) done
apply(sep_auto split!: prod.splits) using assms apply (auto simp del: height_btree.simps dest!: mod_starD list_assn_len)[] using z_split apply(auto)[]
subgoal for _ _ _ _ _ _ _ _ tp tsia' tsin' _ _ _ _ _ _ _ _ _ _ tsia tsin tti ttsi apply(auto dest!: mod_starD list_assn_len simp: prod_assn_def)[] apply(vcg) using False apply(auto dest!: mod_starD list_assn_len) done apply(sep_auto dest!: mod_starD) using assms apply (auto dest!: list_assn_len)[] using assms apply (auto dest!: list_assn_len)[] apply(sep_auto) using assms apply (auto dest!: list_assn_len mod_starD)[] using assms apply (auto dest!: list_assn_len mod_starD)[] (* Issue: we do not know yet what 'subp is pointing at *)
subgoal for _ _ _ _ _ _ tp tsia tsin tti ttsi _ _ _ _ _ _ _ _ tsia' tsin' tti' tsi' subi sepi subp apply(subgoal_tac "z = (subi, sepi)") prefer2 apply (metis assms(3) list_assn_len nth_append_length) apply simp apply(vcg)
subgoal (* still the "IF" branch *) apply(rule entailsI) (* solves impossible case*) using False apply (auto dest!: list_assn_len mod_starD)[] done apply (auto del: impCE) apply(thin_tac "_ ⊨ _")+ apply(rule hoare_triple_preI) (* for each possible combination of \<le> and \<not>\<le>, a subgoal is created *) apply(sep_auto heap add: nodei_rule_ins dest!: mod_starD del: impCE) apply (auto dest!: pfa_assn_len)[] apply (auto dest!: pfa_assn_len list_assn_len)[]
subgoal apply(thin_tac "_ ⊨ _")+ apply(rule hoare_triple_preI) apply(sep_auto split!: btupi.splits del: impCE) apply(auto dest!: btupi_assn_T mod_starD del: impCE)[] apply(rule ent_ex_postI[where x="lsi"]) apply sep_auto apply (sep_auto del: impCE) apply(auto dest!: btupi_assn_Up mod_starD split!: list.splits del: impCE)[]
subgoal for li ai ri apply(rule ent_ex_postI[where x="lsi @ [(li, ai)]"]) apply sep_auto done done apply (sep_auto del: impCE) using assms apply(auto dest!: pfa_assn_len list_assn_len mod_starD)[] using assms apply(auto dest!: pfa_assn_len list_assn_len mod_starD)[] done done next case (Cons rss rrs) thenshow ?thesis apply(subst rebalance_middle_tree_def) apply(rule hoare_triple_preI) apply(sep_auto dest!: mod_starD) using assms apply (auto dest!: list_assn_len)[]
apply(sep_auto split!: prod.splits) using assms apply (auto simp del: height_btree.simps dest!: mod_starD list_assn_len)[] apply(auto)[]
subgoal for _ _ _ _ _ _ _ _ tp tsia' tsin' _ _ _ _ _ _ _ _ _ _ tsia tsin tti ttsi apply(auto dest!: mod_starD list_assn_len simp: prod_assn_def)[] apply(vcg) using False apply(auto dest!: mod_starD list_assn_len) done apply(sep_auto dest!: mod_starD del: impCE) using assms apply (auto dest!: list_assn_len)[] apply(sep_auto del: impCE) using assms apply (auto dest!: list_assn_len mod_starD)[] (* Issue: we do not know yet what 'xa' is pointing at *)
subgoal for list_heap1 list_heap2 _ _ _ _ _ _ tp ttsia' ttsin' tti' ttsi' _ _ _ _ _ _ _ _ ttsia ttsin tti ttsi subi sepi subp apply(subgoal_tac "z = (subi, sepi)") prefer2 apply (metis assms(3) list_assn_len nth_append_length) apply simp apply(vcg)
subgoal (* still the "IF" branch *) apply(rule entailsI) (* solves impossible case*) using False apply (auto dest!: list_assn_len mod_starD)[] done apply simp
subgoal for subtsi subti subts ti subi subtsl ttsl (* TODO different nodei rule here *)
supply R = nodei_rule_ins[where k=k and c="(max (2 * k) (Suc (_ + ttsin)))"and lsi=subts] thm R apply(cases subtsi) apply(sep_auto heap add: R pfa_append_extend_grow_rule dest!: mod_starD del: impCE) (* all of these cases are vacuous *) using assms apply (auto dest!: list_assn_len pfa_assn_len)[] using assms apply (auto dest!: list_assn_len pfa_assn_len)[] using assms apply (auto dest!: list_assn_len pfa_assn_len)[] apply(sep_auto split!: btupi.splits del: impCE) using assms apply (auto dest!: list_assn_len pfa_assn_len)[] apply(thin_tac "_ ⊨ _")+ apply(rule hoare_triple_preI) apply (cases rsi) apply(auto dest!: list_assn_len mod_starD)[] (* TODO avoid creating subgoals here but still split the heap? do we need to do that anyways *)
subgoal for subtsa subtsn mtsa mtsn mtt mtsi _ _ _ _ _ _ _ _ rsubsep _ rrsi rssi (* ensuring that the tree to the right is not none *) apply (cases rsubsep) apply(subgoal_tac "rsubsep = rrsi") prefer2 using assms apply(auto dest!: list_assn_len mod_starD del: impCE simp add: second_last_access)[] apply (simp add: prod_assn_def) apply(cases rss) apply simp
subgoal for rsubi rsepi rsub rsep apply(subgoal_tac "height rsub ≠ 0") prefer2 using assms apply(auto)[] apply(cases rsubi; cases rsub) apply simp+ (* now we may proceed *) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss))
subgoal for rsubi rsubts rsubt rsubtsi' rsubti rsubtsi subnode apply(cases "kvs subnode") apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss))
subgoal for _ rsubtsn subtsmergedi apply (cases subtsmergedi) apply simp apply (vcg (ss))
subgoal for subtsmergeda _
supply R = nodei_rule_ins[where
k=k and
c="max (2*k) (Suc (subtsn + rsubtsn))"and
ls="mts"and
al="Suc (subtsn+rsubtsn)"and
aa=subtsmergeda and
ti=rsubti and
rsi=rsubtsi and
li=subti and a=sep and ai=sep
] thm R apply(rule P_imp_Q_implies_P) apply(auto del: impCE dest!: mod_starD list_assn_len)[] apply(rule hoare_triple_preI) apply(subgoal_tac "subtsn ≤ 2*k ∧ rsubtsn ≤ 2*k") prefer2 apply (auto simp add: is_pfa_def)[] apply (sep_auto heap add: R del: impCE) apply(sep_auto split!: btupi.splits del: impCE) using assms apply(auto dest!: mod_starD list_assn_len)[] apply(sep_auto del: impCE) using assms apply(auto dest!: mod_starD list_assn_len pfa_assn_len del: impCE)[] apply(thin_tac "_ ⊨ _")+ apply(rule hoare_triple_preI) apply (drule btupi_assn_T mod_starD | erule conjE exE)+ apply vcg apply simp
subgoal for rsubtsi ai tsian apply(cases tsian) apply simp apply(rule P_imp_Q_implies_P) apply(rule ent_ex_postI[where x="lsi @ (ai, rsep) # rssi"]) apply(rule ent_ex_postI[where x="(ttsia, ttsin)"]) apply(rule ent_ex_postI[where x="tti"]) apply(rule ent_ex_postI[where x="ttsi"]) using assms apply (sep_auto dest!: list_assn_len) done
subgoal for _ _ rsubp rsubtsa _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ li ai ri apply(sep_auto del: impCE) using assms apply(auto dest!: list_assn_len)[] apply(sep_auto del: impCE) using assms apply(auto dest!: list_assn_len)[] apply(thin_tac "_ ⊨ _")+ apply(rule hoare_triple_preI) apply (drule btupi_assn_Up mod_starD | erule conjE exE)+ apply vcg (* generates two identical subgoals ? *) apply(simp split!: list.split) apply(rule ent_ex_postI[where x="(lsi @ (li, ai) # (ri, rsepi) # rssi)"]) apply(rule ent_ex_postI[where x="(ttsia, ttsin)"]) apply(rule ent_ex_postI[where x="tti"]) apply(rule ent_ex_postI[where x="ttsi"]) using assms apply (sep_auto dest!: list_assn_len) apply(rule ent_ex_postI[where x="(lsi @ (li, ai) # (ri, rsepi) # rssi)"]) apply(rule ent_ex_postI[where x="(ttsia, ttsin)"]) apply(rule ent_ex_postI[where x="tti"]) apply(rule ent_ex_postI[where x="ttsi"]) using assms apply (sep_auto dest!: list_assn_len) done done done done done done done done done qed qed qed qed qed
lemma rebalance_last_tree_rule: assumes"height t = height sub" and"ts = list@[(sub,sep)]" shows"<is_pfa (2*k) tsi tsia * blist_assn k ts tsi * btree_assn k t ti> rebalance_last_tree k tsia ti <λr. btnode_assn k (abs_split.rebalance_last_tree k ts t) r >t" apply(subst rebalance_last_tree_def) apply(rule hoare_triple_preI) using assms apply(auto dest!: mod_starD) apply(subgoal_tac "length tsi - Suc 0 = length list") prefer2 apply(auto dest!: list_assn_len)[] using assms apply(sep_auto)
supply R = rebalance_middle_tree_rule[where
ls="list"and
rs="[]"and
i="length tsi - 1", simplified] apply(cases tsia) using R by blast
partial_function (heap) split_max ::"nat ==> ('a::{default,heap,linorder}) btnode ref option ==> ('a btnode ref option × 'a) Heap" where "split_max k r_t = (case r_t of Some p_t ==> do { t ← !p_t; (case (last t) of None ==> do { (sub,sep) ← pfa_last (kvs t); tsi' ← pfa_butlast (kvs t); p_t := Btnode tsi' sub; return (Some p_t, sep) } | Some x ==> do { (sub,sep) ← split_max k (Some x); p_t' ← rebalance_last_tree k (kvs t) sub; p_t := p_t'; return (Some p_t, sep) }) })
"
lemma split_max_rule: assumes"abs_split.nonempty_lasttreebal t" and"t ≠ Leaf" shows"<btree_assn k t ti> split_max k ti <((btree_assn k) ×a id_assn) (abs_split.split_max k t)>t" using assms proof(induction k t arbitrary: ti rule: abs_split.split_max.induct) case (2 Leaf) thenshow ?caseby auto next case (1 k ts tt) thenshow ?case proof(cases tt) case Leaf thenshow ?thesis apply(subst split_max.simps) apply (vcg) using assms apply auto[] apply (vcg (ss)) apply simp apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply(rule hoare_triple_preI) apply (vcg (ss)) using1apply(auto dest!: mod_starD)[] apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss))
subgoal for tp tsi tti tsi' tnode subsep sub sep apply(cases tsi) apply(rule hoare_triple_preI) apply (vcg) apply(auto simp add: prod_assn_def abs_split.split_max.simps split!: prod.splits)
subgoal for tsia tsin _ _ tsin' lastsep lastsub apply(rule ent_ex_postI[where x="(tsia, tsin')"]) apply(rule ent_ex_postI[where x="sub"]) apply(rule ent_ex_postI[where x="(butlast tsi')"]) using1apply (auto dest!: mod_starD simp add: list_assn_append_Cons_left) apply sep_auto done done apply(sep_auto) done next case (Node tts ttt) have IH_help: "abs_split.nonempty_lasttreebal tt ==> tt ≠ Leaf ==> <btree_assn k (Node tts ttt) (Some ttp)> split_max k (Some ttp) <(btree_assn k ×aid_assn) (abs_split.split_max k tt)>t" for ttp using"1.IH" Node by blast obtain butlasttts l_sub l_sep where ts_split:"tts = butlasttts@[(l_sub, l_sep)]" using1 Node by auto from Node show ?thesis apply(subst split_max.simps) apply (vcg) using1apply auto[] apply (vcg (ss)) apply simp apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) apply (vcg (ss)) using1apply(auto dest!: mod_starD)[] apply (vcg (ss))
subgoal for tp tsi tti tsi' tnode ttp using"1.prems"apply (vcg heap add: IH_help) apply simp apply simp apply(subst prod_assn_def) apply(cases "abs_split.split_max k tt") apply (auto simp del: abs_split.split_max.simps abs_split.rebalance_last_tree.simps height_btree.simps)[]
subgoal for ttsubi ttmaxi ttsub ttmax butlasttsi' lasttssubi butlastts lasttssub lasttssepi lasttssep apply(rule hoare_triple_preI)
supply R = rebalance_last_tree_rule[where k=k and tsia=tsi and ti=ttsubi and t=ttsub and tsi=tsi' and ts=" (butlasttsi' @ [(lasttssubi, lasttssepi)])" and list=butlasttsi' and sub=lasttssubi and sep=lasttssepi] thm R using ts_split (*TODO weird post conditions... *) apply (sep_auto heap add: R
simp del: abs_split.split_max.simps abs_split.rebalance_last_tree.simps height_btree.simps
dest!: mod_starD) apply (metis abs_split.nonempty_lasttreebal.simps(2) abs_split.split_max_height btree.distinct(1)) apply simp apply(rule hoare_triple_preI) apply (simp add: prod_assn_def) apply vcg apply(subst abs_split.split_max.simps) using"1.prems"apply(auto dest!: mod_starD split!: prod.splits btree.splits)
subgoal for _ _ _ _ _ _ _ _ _ _ tp' apply(cases "abs_split.rebalance_last_tree k (butlasttsi' @ [(lasttssubi, lasttssepi)]) ttsub"; cases tp') apply auto apply(rule ent_ex_preI)
subgoal for _ _ tsia' tsin' tt' _ tsi' apply(rule ent_ex_postI[where x="(tsia', tsin')"]) apply(rule ent_ex_postI[where x="tt'"]) apply(rule ent_ex_postI[where x="tsi'"]) apply sep_auto done done done done done qed qed
partial_function (heap) del ::"nat ==> 'a ==> ('a::{default,heap,linorder}) btnode ref option ==> 'a btnode ref option Heap" where "del k x ti = (case ti of None ==> return None | Some p ==> do { node ← !p; i ← imp_split (kvs node) x; tsl ← pfa_length (kvs node); if i < tsl then do { (sub,sep) ← pfa_get (kvs node) i; if sep ≠ x then do { sub' ← del k x sub; kvs' ← pfa_set (kvs node) i (sub',sep); node' ← rebalance_middle_tree k kvs' i (last node); p := node'; return (Some p) } else if sub = None then do{ kvs' ← pfa_delete (kvs node) i; p := (Btnode kvs' (last node)); return (Some p) } else do { sm ← split_max k sub; kvs' ← pfa_set (kvs node) i sm; node' ← rebalance_middle_tree k kvs' i (last node); p := node'; return (Some p) } } else do { t' ← del k x (last node); node' ← rebalance_last_tree k (kvs node) t'; p := node'; return (Some p) } })"
lemma rebalance_middle_tree_update_rule: assumes"height tt = height sub" and"case rs of (rsub,rsep) # list ==> height rsub = height tt | [] ==> True" and"i = length ls" shows"<is_pfa (2 * k) (zs1 @ (x', sep) # zs2) a * btree_assn k sub x' * blist_assn k ls zs1 * id_assn sep sep * blist_assn k rs zs2 * btree_assn k tt ti> rebalance_middle_tree k a i ti <btnode_assn k (abs_split.rebalance_middle_tree k ls sub sep rs tt)>t" proof (cases a) case [simp]: (Pair a n) note R=rebalance_middle_tree_rule[of tt sub rs i ls k "zs1@(x', sep)#zs2" a n sep ti] show ?thesis apply(rule hoare_triple_preI) using R assms apply (sep_auto dest!: mod_starD list_assn_len simp add: prod_assn_def) using assn_times_assoc star_aci(3) by auto qed
lemma del_rule: assumes"bal t"and"sorted (inorder t)"and"root_order k t"and"k > 0" shows"<btree_assn k t ti> del k x ti <btree_assn k (abs_split.del k x t)>t" using assms proof (induction k x t arbitrary: ti rule: abs_split.del.induct) case (1 k x) thenshow ?case apply(subst del.simps) apply sep_auto done next case (2 k x ts tt ti) obtain ls rs where split_ts[simp]: "split ts x = (ls, rs)" by (cases "split ts x") obtain tss lastts_sub lastts_sep where last_ts: "ts = tss@[(lastts_sub, lastts_sep)]" using"2.prems"apply auto by (metis abs_split.isin.cases neq_Nil_rev_conv) show ?case proof(cases "rs") case Nil thenshow ?thesis apply(subst del.simps) apply sep_auto using"2.prems"(2) sorted_inorder_separators apply blast apply(rule hoare_triple_preI) apply (sep_auto) using Nil apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] using Nil apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] using Nil apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] apply (sep_auto heap add: "2.IH"(1)) using"2.prems"apply (auto dest!: mod_starD)[] using"2.prems"apply (auto dest!: mod_starD simp add: sorted_wrt_append)[] using"2.prems" order_impl_root_order apply (auto dest!: mod_starD)[] using"2.prems"apply (auto)[]
subgoal for tp tsia tsin tti tsi i _ _ tti' apply(rule hoare_triple_preI)
supply R = rebalance_last_tree_rule[where t="(abs_split.del k x tt)"and ti=tti' and ts=ts and sub=lastts_sub and list=tss and sep=lastts_sep] thm R using last_ts apply(sep_auto heap add: R) using"2.prems" abs_split.del_height[of k tt x] order_impl_root_order[of k tt] apply (auto dest!: mod_starD)[] apply simp apply(rule hoare_triple_preI) apply (sep_auto) apply(cases "abs_split.rebalance_last_tree k ts (abs_split.del k x tt)") apply(auto simp add: split_relation_alt dest!: mod_starD list_assn_len)
subgoal for tnode apply (cases tnode; sep_auto) done done done next case [simp]: (Cons rrs rss) thenobtain sub sep where [simp]: "rrs = (sub, sep)" by (cases rrs)
consider (sep_n_x) "sep ≠ x" |
(sep_x_Leaf) "sep = x ∧ sub = Leaf" |
(sep_x_Node) "sep = x ∧ (∃ts t. sub = Node ts t)" using btree.exhaust by blast thenshow ?thesis proof(cases) case sep_n_x thenshow ?thesis apply(subst del.simps) apply sep_auto using"2.prems"(2) sorted_inorder_separators apply blast apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply simp apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss))
subgoal for tp tsi ti' tsi' tnode i tsi'l subsep subi sepi (* TODO this causes 4 subgoals *) apply(auto simp add: split_relation_alt list_assn_append_Cons_left;
rule norm_pre_ex_rule; rule norm_pre_ex_rule; rule norm_pre_ex_rule;
rule hoare_triple_preI;
auto dest!: mod_starD)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[]
subgoal for lsi subi rsi apply(subgoal_tac "subi = None") prefer2 apply(auto dest!: list_assn_len)[]
supply R = "2.IH"(2)[of ls rs rrs rss sub sep] thm R using split_ts apply(sep_auto heap add: R) using"2.prems"apply auto[] apply (metis "2.prems"(2) sorted_inorder_induct_subtree) using"2.prems"apply auto[] apply (meson "2.prems"(4) order_impl_root_order) using"2.prems"(4) apply fastforce apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply(vcg (ss)) apply(vcg (ss); simp) apply(cases tsi; simp)
subgoal for subi' _ tsia' tsin'
supply R = rebalance_middle_tree_update_rule thm R (* TODO create a new heap rule, in the node_i style *) apply(auto dest!: list_assn_len)[] apply(rule hoare_triple_preI) apply (sep_auto heap add: R dest!: mod_starD) using"2.prems" abs_split.del_height[of k sub x] order_impl_root_order[of k sub] apply (auto)[] using"2.prems"apply (auto split!: list.splits)[] apply auto[] apply sep_auto
subgoal for _ _ _ _ _ _ _ _ _ _ _ _ _ _ tnode'' apply (cases "(abs_split.rebalance_middle_tree k ls (abs_split.del k x sub) sepi rss tt)"; cases tnode'') apply sep_auto apply sep_auto done done done apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] (* copy pasta of "none" branch *)
subgoal for subnode lsi subi rsi apply(subgoal_tac "subi = Some subnode") prefer2 apply(auto dest!: list_assn_len)[]
supply R = "2.IH"(2)[of ls rs rrs rss sub sep] thm R using split_ts apply(sep_auto heap add: R) using"2.prems"apply auto[] apply (metis "2.prems"(2) sorted_inorder_induct_subtree) using"2.prems"apply auto[] apply (meson "2.prems"(4) order_impl_root_order) using"2.prems"(4) apply fastforce apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply(vcg (ss)) apply(vcg (ss); simp) apply(cases tsi; simp)
subgoal for x' xab a n
supply R = rebalance_middle_tree_update_rule thm R (* TODO create a new heap rule, in the node_i style *) apply(auto dest!: list_assn_len)[] apply(rule hoare_triple_preI) apply (sep_auto heap add: R dest!: mod_starD) using"2.prems" abs_split.del_height[of k sub x] order_impl_root_order[of k sub] apply (auto)[] using"2.prems"apply (auto split!: list.splits)[] apply auto[] apply sep_auto
subgoal for _ _ _ _ _ _ _ _ _ _ _ _ _ _ tnode' apply (cases "(abs_split.rebalance_middle_tree k ls (abs_split.del k x sub) sepi rss tt)"; cases tnode') apply sep_auto apply sep_auto done done done done apply(rule hoare_triple_preI) using Cons apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] done next case sep_x_Leaf thenshow ?thesis apply(subst del.simps) apply sep_auto using"2.prems"(2) sorted_inorder_separators apply blast apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply simp apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss))
subgoal for tp tsi ti' tsi' tnode i tsi'l subsep subi sepi (* TODO this causes 4 subgoals *) apply(auto simp add: split_relation_alt list_assn_append_Cons_left;
rule norm_pre_ex_rule; rule norm_pre_ex_rule; rule norm_pre_ex_rule;
rule hoare_triple_preI;
auto dest!: mod_starD)[] (* the correct subbranch *)
subgoal for lsi subi rsi apply(cases tsi) apply (sep_auto) apply(auto simp add: is_pfa_def dest!: list_assn_len)[] apply (metis add_Suc_right le_imp_less_Suc length_append length_take less_add_Suc1 less_trans_Suc list.size(4) min.cobounded2 not_less_eq) apply vcg apply auto
subgoal for tsin tsia apply(rule ent_ex_postI[where x="(tsia, tsin-1)"]) apply(rule ent_ex_postI[where x="ti'"]) apply(rule ent_ex_postI[where x="lsi@rsi"]) apply (sep_auto dest!: list_assn_len) done done apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[] done apply(rule hoare_triple_preI) using Cons apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] done next case sep_x_Node thenshow ?thesis apply(subst del.simps) apply sep_auto using"2.prems"(2) sorted_inorder_separators apply blast apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss)) apply simp apply(vcg (ss)) apply(vcg (ss)) apply(vcg (ss))
subgoal for subts subt tp tsi ti tsi' tnode i tsi'l subsep subi sepi (* TODO this causes 4 subgoals *) apply(auto simp add: split_relation_alt list_assn_append_Cons_left;
rule norm_pre_ex_rule; rule norm_pre_ex_rule; rule norm_pre_ex_rule;
rule hoare_triple_preI;
auto dest!: mod_starD)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[] (* the correct sub branch *)
subgoal for subnode lsi subi rsi apply(subgoal_tac "subi = Some subnode") apply (simp del: btree_assn.simps)
supply R = split_max_rule[of "Node subts subt" k "Some subnode"] thm R apply(sep_auto heap add: R simp del: btree_assn.simps) using"2.prems"apply(auto dest!: list_assn_len mod_starD simp del: bal.simps order.simps)[]
subgoal proof(goal_cases) case1 thenhave"order k (Node subts subt)" by blast moreoverhave"k > 0" by (simp add: "2.prems"(4)) ultimatelyobtain sub_ls lsub lsep where sub_ts_split: "subts = sub_ls@[(lsub,lsep)]" by (metis abs_split.isin.cases le_0_eq list.size(3) order.simps(2) rev_exhaust zero_less_iff_neq_zero) from1have"bal (Node subts subt)" by auto thenhave"height lsub = height subt" by (simp add: sub_ts_split) thenshow ?thesis using sub_ts_split by blast qed using"2.prems" abs_split.order_bal_nonempty_lasttreebal[of k subt] order_impl_root_order[of k subt] apply(auto)[] apply (auto simp add: split_relation_alt dest!: list_assn_len)[] apply vcg apply auto[] apply(cases "abs_split.split_max k (Node subts subt)"; simp)
subgoal for split_res _ split_sub split_sep apply(cases split_res; simp)
subgoal for split_subi split_sepi
supply R = rebalance_middle_tree_update_rule[
of tt split_sub rss "length lsi" ls k lsi split_subi split_sep rsi tsi ti
] thm R (* id_assn split_sepi doesnt match yet... *) apply(auto simp add: prod_assn_def dest!: list_assn_len) apply (sep_auto) apply(rule hoare_triple_preI) apply(auto dest!: mod_starD)[] apply (sep_auto heap add: R) using"2.prems" abs_split.split_max_height[of k sub] order_impl_root_order[of k sub]
abs_split.order_bal_nonempty_lasttreebal[of k sub] apply (auto)[] using"2.prems" abs_split.split_max_bal[of sub k] order_impl_root_order[of k sub] apply (auto split!: list.splits)[] apply auto[] apply(rule hoare_triple_preI) apply(auto dest!: mod_starD)[]
subgoal for subtsi''a subtsi''n ti subtsi'' tnode' apply(cases "(abs_split.rebalance_middle_tree k ls split_sub split_sep rss tt)"; cases "tnode'") apply auto apply sep_auto done done done apply (auto simp add: split_relation_alt dest!: list_assn_len)[] done apply (auto simp add: split_relation_alt dest!: list_assn_len)[] done apply(rule hoare_triple_preI) using Cons apply (auto simp add: split_relation_alt dest!: mod_starD list_assn_len)[] done qed qed qed
definition reduce_root ::"('a::{default,heap,linorder}) btnode ref option ==> 'a btnode ref option Heap" where "reduce_root ti = (case ti of None ==> return None | Some p_t ==> do { node ← !p_t; tsl ← pfa_length (kvs node); case tsl of 0 ==> return (last node) | _ ==> return ti })"
lemma reduce_root_rule: "<btree_assn k t ti> reduce_root ti <btree_assn k (abs_split.reduce_root t)>t" apply(subst reduce_root_def) apply(cases t; cases ti) apply (sep_auto split!: nat.splits list.splits)+ done
definition delete ::"nat ==> 'a ==> ('a::{default,heap,linorder}) btnode ref option ==> 'a btnode ref option Heap" where "delete k x ti = do { ti' ← del k x ti; reduce_root ti' }"
lemma delete_rule: assumes"bal t"and"root_order k t"and"k > 0"and"sorted (inorder t)" shows"<btree_assn k t ti> delete k x ti <btree_assn k (abs_split.delete k x t)>t" apply(subst delete_def) using assms apply (sep_auto heap add: del_rule reduce_root_rule) done
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.