(* Martin Kleppmann, University of Cambridge VictorB.F.Gomes,UniversityofCambridge DominicP.Mulligan,ArmResearch,Cambridge AlastairBeresford,UniversityofCambridge
*)
section‹Specifying list insertion›
theory Insert_Spec imports OpSet begin
text‹In this section we consider only list insertion. We model an insertion
as a pair (\isa{ID, ref}), where \isa{ref} is either \isa{None}
signifying an insertion at the head of the list) or \isa{Some r}
an insertion immediately after a reference element with ID \isa{r}).
the reference element does not exist, the operation does nothing.
provide two different definitions of the interpretation function for list
: \isa{insert-spec} and \isa{insert-alt}. The \isa{insert-alt} definition
the paper, while \isa{insert-spec} uses the Isabelle/HOL list datatype,
it more suitable for formal reasoning. In a later subsection we prove
the two definitions are in fact equivalent.›
fun insert_spec :: "'oid list ==> ('oid × 'oid option) ==> 'oid list"where "insert_spec xs (oid, None) = oid#xs" | "insert_spec [] (oid, _) = []" | "insert_spec (x#xs) (oid, Some ref) = (if x = ref then x # oid # xs else x # (insert_spec xs (oid, Some ref)))"
fun insert_alt :: "('oid × 'oid option) set ==> ('oid × 'oid) ==> ('oid × 'oid option) set"where "insert_alt list_rel (oid, ref) = ( if ∃n. (ref, n) ∈ list_rel then {(p, n) ∈ list_rel. p ≠ ref} ∪ {(ref, Some oid)} ∪ {(i, n). i = oid ∧ (ref, n) ∈ list_rel} else list_rel)"
text‹\isa{interp-ins} is the sequential interpretation of a set of insertion
. It starts with an empty list as initial state, and then applies
operations from left to right.›
text‹We now specialise the definitions from the abstract OpSet section for list
. \isa{insert-opset} is an opset consisting only of insertion operations, \isa{insert-ops} is the specialisation of the \isa{spec-ops} predicate for
operations. We prove several useful lemmas about \isa{insert-ops}.›
lemma insert_ops_rem_last [dest]: assumes"insert_ops (xs @ [x])" shows"insert_ops xs" using assms insert_ops_def spec_ops_rem_last by blast
lemma insert_ops_rem_cons: assumes"insert_ops (x # xs)" shows"insert_ops xs" using assms insert_ops_def spec_ops_rem_cons by blast
lemma insert_ops_appendD: assumes"insert_ops (xs @ ys)" shows"insert_ops xs" using assms by (induction ys rule: List.rev_induct,
auto, metis insert_ops_rem_last append_assoc)
lemma insert_ops_rem_prefix: assumes"insert_ops (pre @ suf)" shows"insert_ops suf" using assms proof(inductionpre) case Nil thenshow"insert_ops ([] @ suf) ==> insert_ops suf" by auto next case (Cons a pre) have"sorted (map fst suf)" using assms by (simp add: insert_ops_def sorted_append spec_ops_def) moreoverhave"distinct (map fst suf)" using assms by (simp add: insert_ops_def spec_ops_def) ultimatelyshow"insert_ops ((a # pre) @ suf) ==> insert_ops suf" by (simp add: insert_ops_def spec_ops_def) qed
lemma insert_ops_remove1: assumes"insert_ops xs" shows"insert_ops (remove1 x xs)" using assms insert_ops_def spec_ops_remove1 by blast
lemma last_op_greatest: assumes"insert_ops (op_list @ [(oid, oper)])" and"x ∈ set (map fst op_list)" shows"x < oid" using assms spec_ops_id_inc insert_ops_def by metis
lemma insert_ops_ref_older: assumes"insert_ops (pre @ [(oid, Some ref)] @ suf)" shows"ref < oid" using assms by (auto simp add: insert_ops_def spec_ops_def)
lemma insert_ops_memb_ref_older: assumes"insert_ops op_list" and"(oid, Some ref) ∈ set op_list" shows"ref < oid" using assms insert_ops_ref_older split_list_first by fastforce
subsection‹Properties of the \isa{insert-spec} function›
lemma insert_spec_none [simp]: shows"set (insert_spec xs (oid, None)) = set xs ∪ {oid}" by (induction xs, auto simp add: insert_commute sup_commute)
lemma insert_spec_set [simp]: assumes"ref ∈ set xs" shows"set (insert_spec xs (oid, Some ref)) = set xs ∪ {oid}" using assms proof(induction xs) assume"ref ∈ set []" thus"set (insert_spec [] (oid, Some ref)) = set [] ∪ {oid}" by auto next fix a xs assume"ref ∈ set xs ==> set (insert_spec xs (oid, Some ref)) = set xs ∪ {oid}" and"ref ∈ set (a#xs)" thus"set (insert_spec (a#xs) (oid, Some ref)) = set (a#xs) ∪ {oid}" by(cases "a = ref", auto simp add: insert_commute sup_commute) qed
lemma insert_spec_nonex [simp]: assumes"ref ∉ set xs" shows"insert_spec xs (oid, Some ref) = xs" using assms proof(induction xs) show"insert_spec [] (oid, Some ref) = []" by simp next fix a xs assume"ref ∉ set xs ==> insert_spec xs (oid, Some ref) = xs" and"ref ∉ set (a#xs)" thus"insert_spec (a#xs) (oid, Some ref) = a#xs" by(cases "a = ref", auto simp add: insert_commute sup_commute) qed
lemma list_greater_non_memb: fixes oid :: "'oid::{linorder}" assumes"∧x. x ∈ set xs ==> x < oid" and"oid ∈ set xs" shows"False" using assms by blast
lemma inserted_item_ident: assumes"a ∈ set (insert_spec xs (e, i))" and"a ∉ set xs" shows"a = e" using assms proof(induction xs) case Nil thenshow"a = e"by (cases i, auto) next case (Cons x xs) thenshow"a = e" proof(cases i) case None thenshow"a = e"using assms by auto next case (Some ref) thenshow"a = e"using Cons by (case_tac "x = ref", auto) qed qed
lemma insert_spec_distinct [intro]: fixes oid :: "'oid::{linorder}" assumes"distinct xs" and"∧x. x ∈ set xs ==> x < oid" and"ref = Some r ⟶ r < oid" shows"distinct (insert_spec xs (oid, ref))" using assms(1) assms(2) proof(induction xs) show"distinct (insert_spec [] (oid, ref))" by(cases ref, auto) next fix a xs assume IH: "distinct xs ==> (∧x. x ∈ set xs ==> x < oid) ==> distinct (insert_spec xs (oid, ref))" and D: "distinct (a#xs)" and L: "∧x. x ∈ set (a#xs) ==> x < oid" show"distinct (insert_spec (a#xs) (oid, ref))" proof(cases "ref") assume"ref = None" thus"distinct (insert_spec (a#xs) (oid, ref))" using D L by auto next fix id assume S: "ref = Some id"
{ assume EQ: "a = id" hence"id ≠ oid" using D L by auto moreoverhave"id ∉ set xs" using D EQ by auto moreoverhave"oid ∉ set xs" using L by auto ultimatelyhave"id ≠ oid ∧ id ∉ set xs ∧ oid ∉ set xs ∧ distinct xs" using D by auto
} note T = this
{ assume NEQ: "a ≠ id" have0: "a ∉ set (insert_spec xs (oid, Some id))" using D L by(metis distinct.simps(2) insert_spec.simps(1) insert_spec_none insert_spec_nonex
insert_spec_set insert_iff list.set(2) not_less_iff_gr_or_eq) have1: "distinct xs" using D by auto have"∧x. x ∈ set xs ==> x < oid" using L by auto hence"distinct (insert_spec xs (oid, Some id))" using S IH[OF 1] by blast hence"a ∉ set (insert_spec xs (oid, Some id)) ∧ distinct (insert_spec xs (oid, Some id))" using0by auto
} from this S T show"distinct (insert_spec (a # xs) (oid, ref))" by clarsimp qed qed
lemma insert_after_ref: assumes"distinct (xs @ ref # ys)" shows"insert_spec (xs @ ref # ys) (oid, Some ref) = xs @ ref # oid # ys" using assms by (induction xs, auto)
lemma insert_somewhere: assumes"ref = None ∨ (ref = Some r ∧ r ∈ set list)" shows"∃xs ys. list = xs @ ys ∧ insert_spec list (oid, ref) = xs @ oid # ys" using assms proof(induction list) assume"ref = None ∨ ref = Some r ∧ r ∈ set []" thus"∃xs ys. [] = xs @ ys ∧ insert_spec [] (oid, ref) = xs @ oid # ys" proof assume"ref = None" thus"∃xs ys. [] = xs @ ys ∧ insert_spec [] (oid, ref) = xs @ oid # ys" by auto next assume"ref = Some r ∧ r ∈ set []" thus"∃xs ys. [] = xs @ ys ∧ insert_spec [] (oid, ref) = xs @ oid # ys" by auto qed next fix a list assume1: "ref = None ∨ ref = Some r ∧ r ∈ set (a#list)" and IH: "ref = None ∨ ref = Some r ∧ r ∈ set list ==> ∃xs ys. list = xs @ ys ∧ insert_spec list (oid, ref) = xs @ oid # ys" show"∃xs ys. a # list = xs @ ys ∧ insert_spec (a # list) (oid, ref) = xs @ oid # ys" proof(rule disjE[OF 1]) assume"ref = None" thus"∃xs ys. a # list = xs @ ys ∧ insert_spec (a # list) (oid, ref) = xs @ oid # ys" by force next assume"ref = Some r ∧ r ∈ set (a # list)" hence2: "r = a ∨ r ∈ set list"and3: "ref = Some r" by auto show"∃xs ys. a # list = xs @ ys ∧ insert_spec (a # list) (oid, ref) = xs @ oid # ys" proof(rule disjE[OF 2]) assume"r = a" thus"∃xs ys. a # list = xs @ ys ∧ insert_spec (a # list) (oid, ref) = xs @ oid # ys" using3by(metis append_Cons append_Nil insert_spec.simps(3)) next assume"r ∈ set list" from this obtain xs ys where"list = xs @ ys ∧ insert_spec list (oid, ref) = xs @ oid # ys" using IH 3by auto thus"∃xs ys. a # list = xs @ ys ∧ insert_spec (a # list) (oid, ref) = xs @ oid # ys" using3by clarsimp (metis append_Cons append_Nil) qed qed qed
lemma insert_first_part: assumes"ref = None ∨ (ref = Some r ∧ r ∈ set xs)" shows"insert_spec (xs @ ys) (oid, ref) = (insert_spec xs (oid, ref)) @ ys" using assms proof(induction ys rule: rev_induct) assume"ref = None ∨ ref = Some r ∧ r ∈ set xs" thus"insert_spec (xs @ []) (oid, ref) = insert_spec xs (oid, ref) @ []" by auto next fix x xsa assume IH: "ref = None ∨ ref = Some r ∧ r ∈ set xs ==> insert_spec (xs @ xsa) (oid, ref) = insert_spec xs (oid, ref) @ xsa" and"ref = None ∨ ref = Some r ∧ r ∈ set xs" thus"insert_spec (xs @ xsa @ [x]) (oid, ref) = insert_spec xs (oid, ref) @ xsa @ [x]" proof(induction xs) assume"ref = None ∨ ref = Some r ∧ r ∈ set []" thus"insert_spec ([] @ xsa @ [x]) (oid, ref) = insert_spec [] (oid, ref) @ xsa @ [x]" by auto next fix a xs assume1: "ref = None ∨ ref = Some r ∧ r ∈ set (a # xs)" and2: "((ref = None ∨ ref = Some r ∧ r ∈ set xs ==> insert_spec (xs @ xsa) (oid, ref) = insert_spec xs (oid, ref) @ xsa) ==> ref = None ∨ ref = Some r ∧ r ∈ set xs ==> insert_spec (xs @ xsa @ [x]) (oid, ref) = insert_spec xs (oid, ref) @ xsa @ [x])" and3: "(ref = None ∨ ref = Some r ∧ r ∈ set (a # xs) ==> insert_spec ((a # xs) @ xsa) (oid, ref) = insert_spec (a # xs) (oid, ref) @ xsa)" show"insert_spec ((a # xs) @ xsa @ [x]) (oid, ref) = insert_spec (a # xs) (oid, ref) @ xsa @ [x]" proof(rule disjE[OF 1]) assume"ref = None" thus"insert_spec ((a # xs) @ xsa @ [x]) (oid, ref) = insert_spec (a # xs) (oid, ref) @ xsa @ [x]" by auto next assume"ref = Some r ∧ r ∈ set (a # xs)" thus"insert_spec ((a # xs) @ xsa @ [x]) (oid, ref) = insert_spec (a # xs) (oid, ref) @ xsa @ [x]" using23by auto qed qed qed
lemma insert_second_part: assumes"ref = Some r" and"r ∉ set xs" and"r ∈ set ys" shows"insert_spec (xs @ ys) (oid, ref) = xs @ (insert_spec ys (oid, ref))" using assms proof(induction xs) assume"ref = Some r" thus"insert_spec ([] @ ys) (oid, ref) = [] @ insert_spec ys (oid, ref)" by auto next fix a xs assume"ref = Some r"and"r ∉ set (a # xs)"and"r ∈ set ys" and"ref = Some r ==> r ∉ set xs ==> r ∈ set ys ==> insert_spec (xs @ ys) (oid, ref) = xs @ insert_spec ys (oid, ref)" thus"insert_spec ((a # xs) @ ys) (oid, ref) = (a # xs) @ insert_spec ys (oid, ref)" by auto qed
subsection‹Properties of the \isa{interp-ins} function›
lemma interp_ins_subset [simp]: shows"set (interp_ins op_list) ⊆ set (map fst op_list)" proof(induction op_list rule: List.rev_induct) case Nil thenshow"set (interp_ins []) ⊆ set (map fst [])" by (simp add: interp_ins_def) next case (snoc x xs) hence IH: "set (interp_ins xs) ⊆ set (map fst xs)" using interp_ins_def by blast obtain oid ref where x_pair: "x = (oid, ref)" by fastforce hence spec: "interp_ins (xs @ [x]) = insert_spec (interp_ins xs) (oid, ref)" by (simp add: interp_ins_def) thenshow"set (interp_ins (xs @ [x])) ⊆ set (map fst (xs @ [x]))" proof(cases ref) case None thenshow"set (interp_ins (xs @ [x])) ⊆ set (map fst (xs @ [x]))" using IH spec x_pair by auto next case (Some a) thenshow"set (interp_ins (xs @ [x])) ⊆ set (map fst (xs @ [x]))" using IH spec x_pair by (cases "a ∈ set (interp_ins xs)", auto) qed qed
lemma interp_ins_distinct: assumes"insert_ops op_list" shows"distinct (interp_ins op_list)" using assms proof(induction op_list rule: rev_induct) case Nil thenshow"distinct (interp_ins [])" by (simp add: interp_ins_def) next case (snoc x xs) hence IH: "distinct (interp_ins xs)"by blast obtain oid ref where x_pair: "x = (oid, ref)"by force hence"∀x ∈ set (map fst xs). x < oid" using last_op_greatest snoc.prems by blast hence"∀x ∈ set (interp_ins xs). x < oid" using interp_ins_subset by fastforce hence"distinct (insert_spec (interp_ins xs) (oid, ref))" using IH insert_spec_distinct insert_spec_nonex by metis thenshow"distinct (interp_ins (xs @ [x]))" by (simp add: x_pair interp_ins_tail_unfold) qed
subsection‹Equivalence of the two definitions of insertion›
text‹At the beginning of this section we gave two different definitions of
functions for list insertion: \isa{insert-spec} and
isa{insert-alt}. In this section we prove that the two are equivalent.
first define how to derive the successor relation from an Isabelle list.
relation contains (\isa{id}, \isa{None}) if \isa{id} is the last element
the list, and (\isa{id1}, \isa{id2}) if \isa{id1} is immediately
by \isa{id2} in the list.›
text‹\isa{interp-alt} is the equivalent of \isa{interp-ins}, but using
isa{insert-alt} instead of \isa{insert-spec}. To match the paper, it uses a
head element to refer to the beginning of the list.›
definition interp_alt :: "'oid ==> ('oid × 'oid option) list ==> ('oid × 'oid option) set"where "interp_alt head ops ≡ foldl insert_alt {(head, None)} (map (λx. case x of (oid, None) ==> (oid, head) | (oid, Some ref) ==> (oid, ref)) ops)"
lemma succ_rel_set_fst: shows"fst ` (succ_rel xs) = set xs" by (induction xs rule: succ_rel.induct, auto)
lemma succ_rel_functional: assumes"(a, b1) ∈ succ_rel xs" and"(a, b2) ∈ succ_rel xs" and"distinct xs" shows"b1 = b2" using assms proof(induction xs rule: succ_rel.induct) case1 thenshow ?caseby simp next case (2 head) thenshow ?caseby simp next case (3 head x xs) thenshow ?case proof(cases "a = head") case True hence"a ∉ set (x#xs)" using3by auto hence"a ∉ fst ` (succ_rel (x#xs))" using succ_rel_set_fst by metis thenshow"b1 = b2" using3 image_iff by fastforce next case False hence"{(a, b1), (a, b2)} ⊆ succ_rel (x#xs)" using3by auto moreoverhave"distinct (x#xs)" using3by auto ultimatelyshow"b1 = b2" using"3.IH"by auto qed qed
lemma succ_rel_rem_head: assumes"distinct (x # xs)" shows"{(p, n) ∈ succ_rel (x # xs). p ≠ x} = succ_rel xs" proof - have head_notin: "x ∉ fst ` succ_rel xs" using assms by (simp add: succ_rel_set_fst) moreoverobtain y where"(x, y) ∈ succ_rel (x # xs)" by (cases xs, auto) moreoverhave"succ_rel (x # xs) = {(x, y)} ∪ succ_rel xs" using calculation head_notin image_iff by (cases xs, fastforce+) moreoverfrom this have"∧n. (x, n) ∈ succ_rel (x # xs) ==> n = y" by (metis Pair_inject fst_conv head_notin image_eqI insertE insert_is_Un) hence"{(p, n) ∈ succ_rel (x # xs). p ≠ x} = succ_rel (x # xs) - {(x, y)}" by blast moreoverhave"succ_rel (x # xs) - {(x, y)} = succ_rel xs" using image_iff calculation by fastforce ultimatelyshow"{(p, n) ∈ succ_rel (x # xs). p ≠ x} = succ_rel xs" by simp qed
lemma succ_rel_swap_head: assumes"distinct (ref # list)" and"(ref, n) ∈ succ_rel (ref # list)" shows"succ_rel (oid # list) = {(oid, n)} ∪ succ_rel list" proof(cases list) case Nil thenshow ?thesis using assms by auto next case (Cons a list) moreoverfrom this have"n = Some a" by (metis Un_iff assms singletonI succ_rel.simps(3) succ_rel_functional) ultimatelyshow ?thesis by simp qed
lemma succ_rel_insert_alt: assumes"a ≠ ref" and"distinct (oid # a # b # list)" shows"insert_alt (succ_rel (a # b # list)) (oid, ref) = {(a, Some b)} ∪ insert_alt (succ_rel (b # list)) (oid, ref)" proof(cases "∃n. (ref, n) ∈ succ_rel (a # b # list)") case True hence"insert_alt (succ_rel (a # b # list)) (oid, ref) = {(p, n) ∈ succ_rel (a # b # list). p ≠ ref} ∪ {(ref, Some oid)} ∪ {(i, n). i = oid ∧ (ref, n) ∈ succ_rel (a # b # list)}" by simp moreoverhave"{(p, n) ∈ succ_rel (a # b # list). p ≠ ref} = {(a, Some b)} ∪ {(p, n) ∈ succ_rel (b # list). p ≠ ref}" using assms(1) by auto moreoverhave"insert_alt (succ_rel (b # list)) (oid, ref) = {(p, n) ∈ succ_rel (b # list). p ≠ ref} ∪ {(ref, Some oid)} ∪ {(i, n). i = oid ∧ (ref, n) ∈ succ_rel (b # list)}" proof - have"∃n. (ref, n) ∈ succ_rel (b # list)" using assms(1) True by auto thus ?thesis by simp qed moreoverhave"{(i, n). i = oid ∧ (ref, n) ∈ succ_rel (a # b # list)} = {(i, n). i = oid ∧ (ref, n) ∈ succ_rel (b # list)}" using assms(1) by auto ultimatelyshow ?thesis by simp next case False thenshow ?thesis by auto qed
lemma succ_rel_insert_head: assumes"distinct (ref # list)" shows"succ_rel (insert_spec (ref # list) (oid, Some ref)) = insert_alt (succ_rel (ref # list)) (oid, ref)" proof - obtain n where ref_in_rel: "(ref, n) ∈ succ_rel (ref # list)" by (cases list, auto) moreoverfrom this have"{(p, n) ∈ succ_rel (ref # list). p ≠ ref} = succ_rel list" using assms succ_rel_rem_head by (metis (mono_tags, lifting)) moreoverhave"{(i, n). i = oid ∧ (ref, n) ∈ succ_rel (ref # list)} = {(oid, n)}" proof - have"∧nx. (ref, nx) ∈ succ_rel (ref # list) ==> nx = n" using assms by (simp add: succ_rel_functional ref_in_rel) hence"{(i, n) ∈ succ_rel (ref # list). i = ref} ⊆ {(ref, n)}" by blast moreoverhave"{(ref, n)} ⊆ {(i, n) ∈ succ_rel (ref # list). i = ref}" by (simp add: ref_in_rel) ultimatelyshow ?thesis by blast qed moreoverhave"insert_alt (succ_rel (ref # list)) (oid, ref) = {(p, n) ∈ succ_rel (ref # list). p ≠ ref} ∪ {(ref, Some oid)} ∪ {(i, n). i = oid ∧ (ref, n) ∈ succ_rel (ref # list)}" proof - have"∃n. (ref, n) ∈ succ_rel (ref # list)" using ref_in_rel by blast thus ?thesis by simp qed ultimatelyhave"insert_alt (succ_rel (ref # list)) (oid, ref) = succ_rel list ∪ {(ref, Some oid)} ∪ {(oid, n)}" by simp moreoverhave"succ_rel (oid # list) = {(oid, n)} ∪ succ_rel list" using assms ref_in_rel succ_rel_swap_head by metis hence"succ_rel (ref # oid # list) = {(ref, Some oid), (oid, n)} ∪ succ_rel list" by auto ultimatelyshow"succ_rel (insert_spec (ref # list) (oid, Some ref)) = insert_alt (succ_rel (ref # list)) (oid, ref)" by auto qed
lemma succ_rel_insert_later: assumes"succ_rel (insert_spec (b # list) (oid, Some ref)) = insert_alt (succ_rel (b # list)) (oid, ref)" and"a ≠ ref" and"distinct (a # b # list)" shows"succ_rel (insert_spec (a # b # list) (oid, Some ref)) = insert_alt (succ_rel (a # b # list)) (oid, ref)" proof - have"succ_rel (a # b # list) = {(a, Some b)} ∪ succ_rel (b # list)" by simp moreoverhave"insert_spec (a # b # list) (oid, Some ref) = a # (insert_spec (b # list) (oid, Some ref))" using assms(2) by simp hence"succ_rel (insert_spec (a # b # list) (oid, Some ref)) = {(a, Some b)} ∪ succ_rel (insert_spec (b # list) (oid, Some ref))" by auto hence"succ_rel (insert_spec (a # b # list) (oid, Some ref)) = {(a, Some b)} ∪ insert_alt (succ_rel (b # list)) (oid, ref)" using assms(1) by auto moreoverhave"insert_alt (succ_rel (a # b # list)) (oid, ref) = {(a, Some b)} ∪ insert_alt (succ_rel (b # list)) (oid, ref)" using succ_rel_insert_alt assms(2) by auto ultimatelyshow ?thesis by blast qed
lemma succ_rel_insert_Some: assumes"distinct list" shows"succ_rel (insert_spec list (oid, Some ref)) = insert_alt (succ_rel list) (oid, ref)" using assms proof(induction list) case Nil thenshow"succ_rel (insert_spec [] (oid, Some ref)) = insert_alt (succ_rel []) (oid, ref)" by simp next case (Cons a list) hence"distinct (a # list)" by simp thenshow"succ_rel (insert_spec (a # list) (oid, Some ref)) = insert_alt (succ_rel (a # list)) (oid, ref)" proof(cases "a = ref") case True thenshow ?thesis using succ_rel_insert_head ‹distinct (a # list)›by metis next case False hence"a ≠ ref"by simp moreoverhave"succ_rel (insert_spec list (oid, Some ref)) = insert_alt (succ_rel list) (oid, ref)" using Cons.IH Cons.prems by auto ultimatelyshow"succ_rel (insert_spec (a # list) (oid, Some ref)) = insert_alt (succ_rel (a # list)) (oid, ref)" by (cases list, force, metis Cons.prems succ_rel_insert_later) qed qed
text‹The main result of this section, that \isa{insert-spec} and \isa{insert-alt}
equivalent.›
theorem insert_alt_equivalent: assumes"insert_ops ops" and"head ∉ fst ` set ops" and"∧r. Some r ∈ snd ` set ops ==> r ≠ head" shows"succ_rel (head # interp_ins ops) = interp_alt head ops" using assms proof(induction ops rule: List.rev_induct) case Nil thenshow"succ_rel (head # interp_ins []) = interp_alt head []" by (simp add: interp_ins_def interp_alt_def) next case (snoc x xs) have IH: "succ_rel (head # interp_ins xs) = interp_alt head xs" using snoc by auto have distinct_list: "distinct (head # interp_ins xs)" proof - have"distinct (interp_ins xs)" using interp_ins_distinct snoc.prems(1) by blast moreoverhave"set (interp_ins xs) ⊆ fst ` set xs" using interp_ins_subset snoc.prems(1) by fastforce ultimatelyshow"distinct (head # interp_ins xs)" using snoc.prems(2) by auto qed obtain oid r where x_pair: "x = (oid, r)"by force thenshow"succ_rel (head # interp_ins (xs @ [x])) = interp_alt head (xs @ [x])" proof(cases r) case None have"interp_alt head (xs @ [x]) = insert_alt (interp_alt head xs) (oid, head)" by (simp add: interp_alt_def None x_pair) moreoverhave"... = insert_alt (succ_rel (head # interp_ins xs)) (oid, head)" by (simp add: IH) moreoverhave"... = succ_rel (insert_spec (head # interp_ins xs) (oid, Some head))" using distinct_list succ_rel_insert_Some by metis moreoverhave"... = succ_rel (head # (insert_spec (interp_ins xs) (oid, None)))" by auto moreoverhave"... = succ_rel (head # (interp_ins (xs @ [x])))" by (simp add: interp_ins_tail_unfold None x_pair) ultimatelyshow ?thesis by simp next case (Some ref) have"ref ≠ head" by (simp add: Some snoc.prems(3) x_pair) have"interp_alt head (xs @ [x]) = insert_alt (interp_alt head xs) (oid, ref)" by (simp add: interp_alt_def Some x_pair) moreoverhave"... = insert_alt (succ_rel (head # interp_ins xs)) (oid, ref)" by (simp add: IH) moreoverhave"... = succ_rel (insert_spec (head # interp_ins xs) (oid, Some ref))" using distinct_list succ_rel_insert_Some by metis moreoverhave"... = succ_rel (head # (insert_spec (interp_ins xs) (oid, Some ref)))" using‹ref ≠ head›by auto moreoverhave"... = succ_rel (head # (interp_ins (xs @ [x])))" by (simp add: interp_ins_tail_unfold Some x_pair) ultimatelyshow ?thesis by simp qed qed
subsection‹The \isa{list-order} predicate›
text‹\isa{list-order ops x y} holds iff, after interpreting the list of
operations \isa{ops}, the list element with ID \isa{x} appears
the list element with ID \isa{y} in the resulting list. We prove several
about this predicate; in particular, that executing additional insertion
does not change the relative ordering of existing list elements.›
lemma list_orderI: assumes"interp_ins ops = xs @ [x] @ ys @ [y] @ zs" shows"list_order ops x y" using assms by (auto simp add: list_order_def)
lemma list_orderE: assumes"list_order ops x y" shows"∃xs ys zs. interp_ins ops = xs @ [x] @ ys @ [y] @ zs" using assms by (auto simp add: list_order_def)
lemma list_order_memb1: assumes"list_order ops x y" shows"x ∈ set (interp_ins ops)" using assms by (auto simp add: list_order_def)
lemma list_order_memb2: assumes"list_order ops x y" shows"y ∈ set (interp_ins ops)" using assms by (auto simp add: list_order_def)
lemma list_order_trans: assumes"insert_ops op_list" and"list_order op_list x y" and"list_order op_list y z" shows"list_order op_list x z" proof - obtain xxs xys xzs where1: "interp_ins op_list = (xxs@[x]@xys)@(y#xzs)" using assms by (auto simp add: list_order_def interp_ins_def) obtain yxs yys yzs where2: "interp_ins op_list = yxs@y#(yys@[z]@yzs)" using assms by (auto simp add: list_order_def interp_ins_def) have3: "distinct (interp_ins op_list)" using assms interp_ins_distinct by blast hence"xzs = yys@[z]@yzs" using distinct_list_split[OF 3, OF 2, OF 1] by auto hence"interp_ins op_list = xxs@[x]@xys@[y]@yys@[z]@yzs" using123by clarsimp thus"list_order op_list x z" using assms by (metis append.assoc list_orderI) qed
lemma insert_preserves_order: assumes"insert_ops ops"and"insert_ops rest" and"rest = before @ after" and"ops = before @ (oid, ref) # after" shows"∃xs ys zs. interp_ins rest = xs @ zs ∧ interp_ins ops = xs @ ys @ zs" using assms proof(induction after arbitrary: rest ops rule: List.rev_induct) case Nil thenhave1: "interp_ins ops = insert_spec (interp_ins before) (oid, ref)" by (simp add: interp_ins_tail_unfold) thenshow"∃xs ys zs. interp_ins rest = xs @ zs ∧ interp_ins ops = xs @ ys @ zs" proof(cases ref) case None hence"interp_ins rest = [] @ (interp_ins before) ∧ interp_ins ops = [] @ [oid] @ (interp_ins before)" using1 Nil.prems(3) by simp thenshow ?thesis by blast next case (Some a) thenshow ?thesis proof(cases "a ∈ set (interp_ins before)") case True thenobtain xs ys where"interp_ins before = xs @ ys ∧ insert_spec (interp_ins before) (oid, ref) = xs @ oid # ys" using insert_somewhere Some by metis hence"interp_ins rest = xs @ ys ∧ interp_ins ops = xs @ [oid] @ ys" using1 Nil.prems(3) by auto thenshow ?thesis by blast next case False hence"interp_ins ops = (interp_ins rest) @ [] @ []" using insert_spec_nonex 1 Nil.prems(3) Some by simp thenshow ?thesis by blast qed qed next case (snoc oper op_list) thenhave"insert_ops ((before @ (oid, ref) # op_list) @ [oper])" and"insert_ops ((before @ op_list) @ [oper])" by auto thenhave ops1: "insert_ops (before @ op_list)" and ops2: "insert_ops (before @ (oid, ref) # op_list)" using insert_ops_appendD by blast+ thenobtain xs ys zs where IH1: "interp_ins (before @ op_list) = xs @ zs" and IH2: "interp_ins (before @ (oid, ref) # op_list) = xs @ ys @ zs" using snoc.IH by blast obtain i2 r2 where"oper = (i2, r2)"by force thenshow"∃xs ys zs. interp_ins rest = xs @ zs ∧ interp_ins ops = xs @ ys @ zs" proof(cases r2) case None hence"interp_ins (before @ op_list @ [oper]) = (i2 # xs) @ zs" by (metis IH1 ‹oper = (i2, r2)› append.assoc append_Cons insert_spec.simps(1)
interp_ins_tail_unfold) moreoverhave"interp_ins (before @ (oid, ref) # op_list @ [oper]) = (i2 # xs) @ ys @ zs" by (metis IH2 None ‹oper = (i2, r2)› append.assoc append_Cons insert_spec.simps(1)
interp_ins_tail_unfold) ultimatelyshow ?thesis using snoc.prems(3) snoc.prems(4) by blast next case (Some r) thenhave1: "interp_ins (before @ (oid, ref) # op_list @ [(i2, r2)]) = insert_spec (xs @ ys @ zs) (i2, Some r)" by (metis IH2 append.assoc append_Cons interp_ins_tail_unfold) have2: "interp_ins (before @ op_list @ [(i2, r2)]) = insert_spec (xs @ zs) (i2, Some r)" by (metis IH1 append.assoc interp_ins_tail_unfold Some)
consider (r_xs) "r ∈ set xs" | (r_ys) "r ∈ set ys" | (r_zs) "r ∈ set zs" |
(r_nonex) "r ∉ set (xs @ ys @ zs)" by auto thenshow"∃xs ys zs. interp_ins rest = xs @ zs ∧ interp_ins ops = xs @ ys @ zs" proof(cases) case r_xs from this have"insert_spec (xs @ ys @ zs) (i2, Some r) = (insert_spec xs (i2, Some r)) @ ys @ zs" by (meson insert_first_part) moreoverhave"insert_spec (xs @ zs) (i2, Some r) = (insert_spec xs (i2, Some r)) @ zs" by (meson r_xs insert_first_part) ultimatelyshow ?thesis using12‹oper = (i2, r2)› snoc.prems by auto next case r_ys hence"r ∉ set xs"and"r ∉ set zs" using IH2 ops2 interp_ins_distinct by force+ moreoverfrom this have"insert_spec (xs @ ys @ zs) (i2, Some r) = xs @ (insert_spec ys (i2, Some r)) @ zs" using insert_first_part insert_second_part insert_spec_nonex by (metis Some UnE r_ys set_append) moreoverhave"insert_spec (xs @ zs) (i2, Some r) = xs @ zs" by (simp add: Some calculation(1) calculation(2)) ultimatelyshow ?thesis using12‹oper = (i2, r2)› snoc.prems by auto next case r_zs hence"r ∉ set xs"and"r ∉ set ys" using IH2 ops2 interp_ins_distinct by force+ moreoverfrom this have"insert_spec (xs @ ys @ zs) (i2, Some r) = xs @ ys @ (insert_spec zs (i2, Some r))" by (metis Some UnE insert_second_part insert_spec_nonex set_append) moreoverhave"insert_spec (xs @ zs) (i2, Some r) = xs @ (insert_spec zs (i2, Some r))" by (simp add: r_zs calculation(1) insert_second_part) ultimatelyshow ?thesis using12‹oper = (i2, r2)› snoc.prems by auto next case r_nonex thenhave"insert_spec (xs @ ys @ zs) (i2, Some r) = xs @ ys @ zs" by simp moreoverhave"insert_spec (xs @ zs) (i2, Some r) = xs @ zs" using r_nonex by simp ultimatelyshow ?thesis using12‹oper = (i2, r2)› snoc.prems by auto qed qed qed
lemma distinct_fst: assumes"distinct (map fst A)" shows"distinct A" using assms by (induction A) auto
lemma subset_distinct_le: assumes"set A ⊆ set B"and"distinct A"and"distinct B" shows"length A ≤ length B" using assms proof(induction B arbitrary: A) case Nil thenshow"length A ≤ length []"by simp next case (Cons a B) thenshow"length A ≤ length (a # B)" proof(cases "a ∈ set A") case True have"set (remove1 a A) ⊆ set B" using Cons.prems by auto hence"length (remove1 a A) ≤ length B" using Cons.IH Cons.prems by auto thenshow"length A ≤ length (a # B)" by (simp add: True length_remove1) next case False hence"set A ⊆ set B" using Cons.prems by auto hence"length A ≤ length B" using Cons.IH Cons.prems by auto thenshow"length A ≤ length (a # B)" by simp qed qed
lemma set_subset_length_eq: assumes"set A ⊆ set B"and"length B ≤ length A" and"distinct A"and"distinct B" shows"set A = set B" proof - have"length A ≤ length B" using assms by (simp add: subset_distinct_le) moreoverfrom this have"card (set A) = card (set B)" using assms by (simp add: distinct_card le_antisym) ultimatelyshow"set A = set B" using assms(1) by (simp add: card_subset_eq) qed
lemma length_diff_Suc_exists: assumes"length xs - length ys = Suc m" and"set ys ⊆ set xs" and"distinct ys"and"distinct xs" shows"∃e. e ∈ set xs ∧ e ∉ set ys" using assms proof(induction xs arbitrary: ys) case Nil thenshow"∃e. e ∈ set [] ∧ e ∉ set ys" by simp next case (Cons a xs) thenshow"∃e. e ∈ set (a # xs) ∧ e ∉ set ys" proof(cases "a ∈ set ys") case True have IH: "∃e. e ∈ set xs ∧ e ∉ set (remove1 a ys)" proof - have"length xs - length (remove1 a ys) = Suc m" by (metis Cons.prems(1) One_nat_def Suc_pred True diff_Suc_Suc length_Cons
length_pos_if_in_set length_remove1) moreoverhave"set (remove1 a ys) ⊆ set xs" using Cons.prems by auto ultimatelyshow ?thesis by (meson Cons.IH Cons.prems distinct.simps(2) distinct_remove1) qed moreoverhave"set ys - {a} ⊆ set xs" using Cons.prems(2) by auto ultimatelyshow"∃e. e ∈ set (a # xs) ∧ e ∉ set ys" by (metis Cons.prems(4) distinct.simps(2) in_set_remove1 set_subset_Cons subsetCE) next case False thenshow"∃e. e ∈ set (a # xs) ∧ e ∉ set ys" by auto qed qed
lemma list_order_monotonic: assumes"insert_ops A"and"insert_ops B" and"set A ⊆ set B" and"list_order A x y" shows"list_order B x y" using assms proof(induction rule: measure_induct_rule[where f="λx. (length x - length A)"]) case (less xa) have"distinct (map fst A)"and"distinct (map fst xa)"and "sorted (map fst A)"and"sorted (map fst xa)" using less.prems by (auto simp add: insert_ops_def spec_ops_def) hence"distinct A"and"distinct xa" by (auto simp add: distinct_fst) thenshow"list_order xa x y" proof(cases "length xa - length A") case0 hence"set A = set xa" using set_subset_length_eq less.prems(3) ‹distinct A›‹distinct xa› diff_is_0_eq by blast hence"A = xa" using‹distinct (map fst A)›‹distinct (map fst xa)› ‹sorted (map fst A)›‹sorted (map fst xa)› map_sorted_distinct_set_unique by (metis distinct_map less.prems(3) subset_Un_eq) thenshow"list_order xa x y" using less.prems(4) by blast next case (Suc nat) thenobtain e where"e ∈ set xa"and"e ∉ set A" using length_diff_Suc_exists ‹distinct A›‹distinct xa› less.prems(3) by blast hence IH: "list_order (remove1 e xa) x y" proof - have"length (remove1 e xa) - length A < Suc nat" using diff_Suc_1 diff_commute length_remove1 less_Suc_eq Suc ‹e ∈ set xa›by metis moreoverhave"insert_ops (remove1 e xa)" by (simp add: insert_ops_remove1 less.prems(2)) moreoverhave"set A ⊆ set (remove1 e xa)" by (metis (no_types, lifting) ‹e ∉ set A› in_set_remove1 less.prems(3) rev_subsetD subsetI) ultimatelyshow ?thesis by (simp add: Suc less.IH less.prems(1) less.prems(4)) qed thenobtain xs ys zs where"interp_ins (remove1 e xa) = xs @ x # ys @ y # zs" using list_order_def by fastforce moreoverobtain oid ref where e_pair: "e = (oid, ref)" by fastforce moreoverobtain ps ss where xa_split: "xa = ps @ [e] @ ss"and"e ∉ set ps" using split_list_first ‹e ∈ set xa›by fastforce hence"remove1 e (ps @ e # ss) = ps @ ss" by (simp add: remove1_append) moreoverfrom this have"insert_ops (ps @ ss)"and"insert_ops (ps @ e # ss)" using xa_split less.prems(2) by (metis append_Cons append_Nil insert_ops_remove1, auto) thenobtain xsa ysa zsa where"interp_ins (ps @ ss) = xsa @ zsa" and interp_xa: "interp_ins (ps @ (oid, ref) # ss) = xsa @ ysa @ zsa" using insert_preserves_order e_pair by metis moreoverhave xsa_zsa: "xsa @ zsa = xs @ x # ys @ y # zs" using interp_ins_def remove1_append calculation xa_split by auto thenshow"list_order xa x y" proof(cases "length xsa ≤ length xs") case True thenobtain ts where"xsa@ts = xs" using app_length_lt_exists xsa_zsa by blast hence"interp_ins xa = (xsa @ ysa @ ts) @ [x] @ ys @ [y] @ zs" using calculation xa_split by auto thenshow"list_order xa x y" using list_order_def by blast next case False thenshow"list_order xa x y" proof(cases "length xsa ≤ length (xs @ x # ys)") case True have xsa_zsa1: "xsa @ zsa = (xs @ x # ys) @ (y # zs)" by (simp add: xsa_zsa) thenobtain us where"xsa @ us = xs @ x # ys" using app_length_lt_exists True by blast moreoverfrom this have"xs @ x # (drop (Suc (length xs)) xsa) = xsa" using append_eq_append_conv_if id_take_nth_drop linorder_not_less
nth_append nth_append_length False by metis moreoverhave"us @ y # zs = zsa" by (metis True xsa_zsa1 append_eq_append_conv_if append_eq_conv_conj calculation(1)) ultimatelyhave"interp_ins xa = xs @ [x] @ ((drop (Suc (length xs)) xsa) @ ysa @ us) @ [y] @ zs" by (simp add: e_pair interp_xa xa_split) thenshow"list_order xa x y" using list_order_def by blast next case False hence"length (xs @ x # ys) < length xsa" using not_less by blast hence"length (xs @ x # ys @ [y]) ≤ length xsa" by simp moreoverhave"(xs @ x # ys @ [y]) @ zs = xsa @ zsa" by (simp add: xsa_zsa) ultimatelyobtain vs where"(xs @ x # ys @ [y]) @ vs = xsa" using app_length_lt_exists by blast hence"xsa @ ysa @ zsa = xs @ [x] @ ys @ [y] @ vs @ ysa @ zsa" by simp hence"interp_ins xa = xs @ [x] @ ys @ [y] @ (vs @ ysa @ zsa)" using e_pair interp_xa xa_split by auto thenshow"list_order xa x y" using list_order_def by blast qed qed qed qed
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 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.