fun invar :: "'a aa_tree \ bool" where "invar Leaf = True" | "invar (Node l (a, h) r) =
(invar l \<and> invar r \<and>
h = lvl l + 1 \<and> (h = lvl r + 1 \<or> (\<exists>lr b rr. r = Node lr (b,h) rr \<and> h = lvl rr + 1)))"
fun skew :: "'a aa_tree \ 'a aa_tree" where "skew (Node (Node t1 (b, lvb) t2) (a, lva) t3) =
(if lva = lvb then Node t1 (b, lvb) (Node t2 (a, lva) t3) else Node (Node t1 (b, lvb) t2) (a, lva) t3)" | "skew t = t"
fun split :: "'a aa_tree \ 'a aa_tree" where "split (Node t1 (a, lva) (Node t2 (b, lvb) (Node t3 (c, lvc) t4))) =
(if lva = lvb \<and> lvb = lvc \<comment> \<open>\<open>lva = lvc\<close> suffices\<close> then Node (Node t1 (a,lva) t2) (b,lva+1) (Node t3 (c, lva) t4)
else Node t1 (a,lva) (Node t2 (b,lvb) (Node t3 (c,lvc) t4)))" | "split t = t"
hide_const (open) insert
fun insert :: "'a::linorder \ 'a aa_tree \ 'a aa_tree" where "insert x Leaf = Node Leaf (x, 1) Leaf" | "insert x (Node t1 (a,lv) t2) =
(case cmp x a of
LT \<Rightarrow> split (skew (Node (insert x t1) (a,lv) t2)) |
GT \<Rightarrow> split (skew (Node t1 (a,lv) (insert x t2))) |
EQ \<Rightarrow> Node t1 (x, lv) t2)"
definition adjust :: "'a aa_tree \ 'a aa_tree" where "adjust t =
(case t of
Node l (x,lv) r \<Rightarrow>
(if lvl l >= lv-1 \<and> lvl r >= lv-1 then t else if lvl r < lv-1 \<and> sngl l then skew (Node l (x,lv-1) r) else if lvl r < lv-1 thencase l of
Node t1 (a,lva) (Node t2 (b,lvb) t3) \<Rightarrow> Node (Node t1 (a,lva) t2) (b,lvb+1) (Node t3 (x,lv-1) r)
else if lvl r < lv then split (Node l (x,lv-1) r)
else case r of
Node t1 (b,lvb) t4 \<Rightarrow>
(case t1 of
Node t2 (a,lva) t3 \<Rightarrow> Node (Node l (x,lv-1) t2) (a,lva+1)
(split (Node t3 (b, if sngl t1 then lva else lva+1) t4)))))"
text\<open>In the paper, the last case of \<^const>\<open>adjust\<close> is expressed with the help of an
incorrect auxiliary function\texttt{nlvl}.
Function\<open>split_max\<close> below is called \texttt{dellrg} in the paper.
The latter is incorrect for two reasons: \texttt{dellrg} is meant to delete the largest
element but recurses on the left instead of the right subtree; the invariant is not restored.\<close>
fun split_max :: "'a aa_tree \ 'a aa_tree * 'a" where "split_max (Node l (a,lv) Leaf) = (l,a)" | "split_max (Node l (a,lv) r) = (let (r',b) = split_max r in (adjust(Node l (a,lv) r'), b))"
fun delete :: "'a::linorder \ 'a aa_tree \ 'a aa_tree" where "delete _ Leaf = Leaf" | "delete x (Node l (a,lv) r) =
(case cmp x a of
LT \<Rightarrow> adjust (Node (delete x l) (a,lv) r) |
GT \<Rightarrow> adjust (Node l (a,lv) (delete x r)) |
EQ \<Rightarrow> (if l = Leaf then r
else let (l',b) = split_max l in adjust (Node l' (b,lv) r)))"
fun pre_adjust where "pre_adjust (Node l (a,lv) r) = (invar l \ invar r \
((lv = lvl l + 1 \<and> (lv = lvl r + 1 \<or> lv = lvl r + 2 \<or> lv = lvl r \<and> sngl r)) \<or>
(lv = lvl l + 2 \<and> (lv = lvl r + 1 \<or> lv = lvl r \<and> sngl r))))"
declare pre_adjust.simps [simp del]
subsection "Auxiliary Proofs"
lemma split_case: "split t = (case t of
Node t1 (x,lvx) (Node t2 (y,lvy) (Node t3 (z,lvz) t4)) \<Rightarrow>
(if lvx = lvy \<and> lvy = lvz then Node (Node t1 (x,lvx) t2) (y,lvx+1) (Node t3 (z,lvx) t4)
else t)
| t \<Rightarrow> t)" by(auto split: tree.split)
lemma skew_case: "skew t = (case t of
Node (Node t1 (y,lvy) t2) (x,lvx) t3 \<Rightarrow>
(if lvx = lvy then Node t1 (y, lvx) (Node t2 (x,lvx) t3) else t)
| t \<Rightarrow> t)" by(auto split: tree.split)
lemma lvl_0_iff: "invar t \ lvl t = 0 \ t = Leaf" by(cases t) auto
lemma lvl_Suc_iff: "lvl t = Suc n \ (\ l a r. t = Node l (a,Suc n) r)" by(cases t) auto
lemma lvl_skew: "lvl (skew t) = lvl t" by(cases t rule: skew.cases) auto
lemma lvl_split: "lvl (split t) = lvl t \ lvl (split t) = lvl t + 1 \ sngl (split t)" by(cases t rule: split.cases) auto
lemma invar_NodeLeaf[simp]: "invar (Node l (x,lv) Leaf) = (invar l \ lv = Suc (lvl l) \ lv = Suc 0)" by simp
lemma sngl_if_invar: "invar (Node l (a, n) r) \ n = lvl r \ sngl r" by(cases r rule: sngl.cases) clarsimp+
subsection "Invariance"
subsubsection "Proofs for insert"
lemma lvl_insert_aux: "lvl (insert x t) = lvl t \ lvl (insert x t) = lvl t + 1 \ sngl (insert x t)" apply(induction t) apply (auto simp: lvl_skew) apply (metis Suc_eq_plus1 lvl.simps(2) lvl_split lvl_skew)+ done
lemma lvl_insert: obtains
(Same) "lvl (insert x t) = lvl t" |
(Incr) "lvl (insert x t) = lvl t + 1""sngl (insert x t)" using lvl_insert_aux by blast
lemma lvl_insert_sngl: "invar t \ sngl t \ lvl(insert x t) = lvl t" proof (induction t rule: insert.induct) case (2 x t1 a lv t2)
consider (LT) "x < a" | (GT) "x > a" | (EQ) "x = a" using less_linear by blast thus ?caseproof cases case LT thus ?thesis using 2 by (auto simp add: skew_case split_case split: tree.splits) next case GT thus ?thesis using 2 proof (cases t1 rule: tree2_cases) case Node thus ?thesis using 2 GT apply (auto simp add: skew_case split_case split: tree.splits) by (metis less_not_refl2 lvl.simps(2) lvl_insert_aux n_not_Suc_n sngl.simps(3))+ qed (auto simp add: lvl_0_iff) qed simp qed simp
lemma skew_invar: "invar t \ skew t = t" by(cases t rule: skew.cases) auto
lemma split_invar: "invar t \ split t = t" by(cases t rule: split.cases) clarsimp+
lemma invar_NodeL: "\ invar(Node l (x, n) r); invar l'; lvl l' = lvl l \ \ invar(Node l' (x, n) r)" by(auto)
lemma invar_NodeR: "\ invar(Node l (x, n) r); n = lvl r + 1; invar r'; lvl r' = lvl r \ \ invar(Node l (x, n) r')" by(auto)
lemma invar_NodeR2: "\ invar(Node l (x, n) r); sngl r'; n = lvl r + 1; invar r'; lvl r' = n \ \ invar(Node l (x, n) r')" by(cases r' rule: sngl.cases) clarsimp+
lemma lvl_insert_incr_iff: "(lvl(insert a t) = lvl t + 1) \
(\<exists>l x r. insert a t = Node l (x, lvl t + 1) r \<and> lvl l = lvl r)" apply(cases t rule: tree2_cases) apply(auto simp add: skew_case split_case split: if_splits) apply(auto split: tree.splits if_splits) done
lemma invar_insert: "invar t \ invar(insert a t)" proof(induction t rule: tree2_induct) case N: (Node l x n r) hence il: "invar l"and ir: "invar r"by auto note iil = N.IH(1)[OF il] note iir = N.IH(2)[OF ir] let ?t = "Node l (x, n) r" have"a < x \ a = x \ x < a" by auto moreover have ?caseif"a < x" proof (cases rule: lvl_insert[of a l]) case (Same) thus ?thesis using\<open>a<x\<close> invar_NodeL[OF N.prems iil Same] by (simp add: skew_invar split_invar del: invar.simps) next case (Incr) thenobtain t1 w t2 where ial[simp]: "insert a l = Node t1 (w, n) t2" using N.prems by (auto simp: lvl_Suc_iff) have l12: "lvl t1 = lvl t2" by (metis Incr(1) ial lvl_insert_incr_iff tree.inject) have"insert a ?t = split(skew(Node (insert a l) (x,n) r))" by(simp add: \<open>a<x\<close>) alsohave"skew(Node (insert a l) (x,n) r) = Node t1 (w,n) (Node t2 (x,n) r)" by(simp) alsohave"invar(split \)" proof (cases r rule: tree2_cases) case Leaf hence"l = Leaf"using N.prems by(auto simp: lvl_0_iff) thus ?thesis using Leaf ial by simp next case [simp]: (Node t3 y m t4) show ?thesis (*using N(3) iil l12 by(auto)*) proof cases assume"m = n"thus ?thesis using N(3) iil by(auto) next assume"m \ n" thus ?thesis using N(3) iil l12 by(auto) qed qed finallyshow ?thesis . qed moreover have ?caseif"x < a" proof - from\<open>invar ?t\<close> have "n = lvl r \<or> n = lvl r + 1" by auto thus ?case proof assume 0: "n = lvl r" have"insert a ?t = split(skew(Node l (x, n) (insert a r)))" using\<open>a>x\<close> by(auto) alsohave"skew(Node l (x,n) (insert a r)) = Node l (x,n) (insert a r)" using N.prems by(simp add: skew_case split: tree.split) alsohave"invar(split \)" proof - from lvl_insert_sngl[OF ir sngl_if_invar[OF \<open>invar ?t\<close> 0], of a] obtain t1 y t2 where iar: "insert a r = Node t1 (y,n) t2" using N.prems 0 by (auto simp: lvl_Suc_iff) from N.prems iar 0 iir show ?thesis by (auto simp: split_case split: tree.splits) qed finallyshow ?thesis . next assume 1: "n = lvl r + 1" hence"sngl ?t"by(cases r) auto show ?thesis proof (cases rule: lvl_insert[of a r]) case (Same) show ?thesis using\<open>x<a\<close> il ir invar_NodeR[OF N.prems 1 iir Same] by (auto simp add: skew_invar split_invar) next case (Incr) thus ?thesis using invar_NodeR2[OF \<open>invar ?t\<close> Incr(2) 1 iir] 1 \<open>x < a\<close> by (auto simp add: skew_invar split_invar split: if_splits) qed qed qed moreover have"a = x \ ?case" using N.prems by auto ultimatelyshow ?caseby blast qed simp
lemma invar_adjust: assumespre: "pre_adjust (Node l (a,lv) r)" shows"invar(adjust (Node l (a,lv) r))" usingpreproof (cases rule: pre_cases) case (tDouble) thus ?thesis unfolding adjust_def by (cases r) (auto simp: invar.simps(2)) next case (rDown) from rDown obtain llv ll la lr where l: "l = Node ll (la, llv) lr"by (cases l) auto from rDown show ?thesis unfolding adjust_def by (auto simp: l invar.simps(2) split: tree.splits) next case (lDown_tDouble) from lDown_tDouble obtain rlv rr ra rl where r: "r = Node rl (ra, rlv) rr"by (cases r) auto from lDown_tDouble and r obtain rrlv rrr rra rrl where
rr :"rr = Node rrr (rra, rrlv) rrl"by (cases rr) auto from lDown_tDouble show ?thesis unfolding adjust_def r rr apply (cases rl rule: tree2_cases) apply (auto simp add: invar.simps(2) split!: if_split) using lDown_tDouble by (auto simp: split_case lvl_0_iff elim:lvl.elims split: tree.split) qed (auto simp: split_case invar.simps(2) adjust_def split: tree.splits)
lemma lvl_adjust: assumes"pre_adjust (Node l (a,lv) r)" shows"lv = lvl (adjust(Node l (a,lv) r)) \ lv = lvl (adjust(Node l (a,lv) r)) + 1" using assms(1) proof(cases rule: pre_cases) case lDown_tSngl thus ?thesis using lvl_split[of "\l, (a, lvl r), r\"] by (auto simp: adjust_def) next case lDown_tDouble thus ?thesis by (auto simp: adjust_def invar.simps(2) split: tree.split) qed (auto simp: adjust_def split: tree.splits)
lemma sngl_adjust: assumes"pre_adjust (Node l (a,lv) r)" "sngl \l, (a, lv), r\" "lv = lvl (adjust \l, (a, lv), r\)" shows"sngl (adjust \l, (a, lv), r\)" using assms proof (cases rule: pre_cases) case rDown thus ?thesis using assms(2,3) unfolding adjust_def by (auto simp add: skew_case) (auto split: tree.split) qed (auto simp: adjust_def skew_case split_case split: tree.split)
definition"post_del t t' ==
invar t' \
(lvl t' = lvl t \ lvl t' + 1 = lvl t) \
(lvl t' = lvl t \ sngl t \ sngl t')"
show ?case proof (cases rule: linorder_cases[of x a]) case less thus ?thesis using Node.prems by (simp add: post_del_adjL preL) next case greater thus ?thesis using Node.prems by (simp add: post_del_adjR preR post_r') next case equal show ?thesis proof cases assume"l = Leaf"thus ?thesis using equal Node.prems by(auto simp: post_del_def invar.simps(2)) next assume"l \ Leaf" thus ?thesis using equal by simp (metis Node.prems inv_l post_del_adjL post_split_max pre_adj_if_postL) qed qed qed (simp add: post_del_def)
lemma split_maxD: "\ split_max t = (t',x); t \ Leaf; invar t \ \ inorder t' @ [x] = inorder t" by(induction t arbitrary: t' rule: split_max.induct)
(auto simp: sorted_lems inorder_adjust pre_adj_if_postR post_split_max split: prod.splits)
lemma inorder_delete: "invar t \ sorted(inorder t) \ inorder(delete x t) = del_list x (inorder t)" by(induction t)
(auto simp: del_list_simps inorder_adjust pre_adj_if_postL pre_adj_if_postR
post_split_max post_delete split_maxD split: prod.splits)
interpretation S: Set_by_Ordered where empty = empty and isin = isin and insert = insert and delete = delete and inorder = inorder and inv = invar proof (standard, goal_cases) case 1 show ?caseby (simp add: empty_def) next case 2 thus ?caseby(simp add: isin_set_inorder) next case 3 thus ?caseby(simp add: inorder_insert) next case 4 thus ?caseby(simp add: inorder_delete) next case 5 thus ?caseby(simp add: empty_def) next case 6 thus ?caseby(simp add: invar_insert) next case 7 thus ?caseusing post_delete by(auto simp: post_del_def) qed
end
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
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 ist noch experimentell.