Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/Complx/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 29.4.2026 mit Größe 5 kB image not shown  

Quelle  Insert_Spec.thy

  Sprache: Isabelle
 

(* Martin Kleppmann, University of Cambridge
   Victor B. F. Gomes, University of Cambridge
   Dominic P. Mulligan, Arm Research, Cambridge
   Alastair Beresford, University of Cambridge
*)


sectionSpecifying list insertion

theory Insert_Spec
  imports OpSet
begin

textIn 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.


definition interp_ins :: "('oid × 'oid option) list ==> 'oid list" where
  "interp_ins ops foldl insert_spec [] ops"


subsection The \isa{insert-ops} predicate

textWe 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}.


locale insert_opset = opset opset set_option
  for opset :: "('oid::{linorder} × 'oid option) set"

definition insert_ops :: "('oid::{linorder} × 'oid option) list ==> bool" where
  "insert_ops list spec_ops list set_option"

lemma insert_ops_NilI [intro!]:
  shows "insert_ops []"
  by (auto simp add: insert_ops_def spec_ops_def)

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(induction pre)
  case Nil
  then show "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)
  moreover have "distinct (map fst suf)"
    using assms by (simp add: insert_ops_def spec_ops_def)
  ultimately show "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
  then show "a = e" by (cases i, auto)
next
  case (Cons x xs)
  then show "a = e"
  proof(cases i)
    case None
    then show "a = e" using assms by auto
  next
    case (Some ref)
    then show "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(2proof(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
      moreover have "id set xs"
        using D EQ by auto
      moreover have "oid set xs"
        using L by auto
      ultimately have "id oid id set xs oid set xs distinct xs"
        using D by auto
    }
    note T = this
    {
      assume NEQ: "a id"
      have 0"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)
      have 1"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 1by blast
      hence "a set (insert_spec xs (oid, Some id)) distinct (insert_spec xs (oid, Some id))"
        using 0 by 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
  assume 1"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)"
    hence 2"r = a r set list" and 3"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"
        using 3 by(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 3 by auto
      thus "xs ys. a # list = xs @ ys insert_spec (a # list) (oid, ref) = xs @ oid # ys"
        using 3 by 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
    assume 1"ref = None ref = Some r r set (a # xs)"
      and 2"((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])"
      and 3"(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]"
        using 2 3 by 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_empty [simp]:
  shows "interp_ins [] = []"
  by (simp add: interp_ins_def)

lemma interp_ins_tail_unfold:
  shows "interp_ins (xs @ [x]) = insert_spec (interp_ins xs) x"
  by (clarsimp simp add: interp_ins_def)

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
  then show "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)
  then show "set (interp_ins (xs @ [x])) set (map fst (xs @ [x]))"
  proof(cases ref)
    case None
    then show "set (interp_ins (xs @ [x])) set (map fst (xs @ [x]))"
      using IH spec x_pair by auto
  next
    case (Some a)
    then show "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
  then show "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
  then show "distinct (interp_ins (xs @ [x]))"
    by (simp add: x_pair interp_ins_tail_unfold)
qed


subsection Equivalence of the two definitions of insertion

textAt 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.


fun succ_rel :: "'oid list ==> ('oid × 'oid option) set" where
  "succ_rel [] = {}" |
  "succ_rel [head] = {(head, None)}" |
  "succ_rel (head#x#xs) = {(head, Some x)} succ_rel (x#xs)"

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)
  case 1
  then show ?case by simp
next
  case (2 head)
  then show ?case by simp
next
  case (3 head x xs)
  then show ?case
  proof(cases "a = head")
    case True
    hence "a set (x#xs)"
      using 3 by auto
    hence "a fst ` (succ_rel (x#xs))"
      using succ_rel_set_fst by metis
    then show "b1 = b2"
      using 3 image_iff by fastforce
  next
    case False
    hence "{(a, b1), (a, b2)} succ_rel (x#xs)"
      using 3 by auto
    moreover have "distinct (x#xs)"
      using 3 by auto
    ultimately show "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)
  moreover obtain y where "(x, y) succ_rel (x # xs)"
    by (cases xs, auto)
  moreover have "succ_rel (x # xs) = {(x, y)} succ_rel xs"
    using calculation head_notin image_iff by (cases xs, fastforce+)
  moreover from 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
  moreover have "succ_rel (x # xs) - {(x, y)} = succ_rel xs"
    using image_iff calculation by fastforce
  ultimately show "{(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
  then show ?thesis using assms by auto
next
  case (Cons a list)
  moreover from this have "n = Some a"
    by (metis Un_iff assms singletonI succ_rel.simps(3) succ_rel_functional)
  ultimately show ?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
  moreover have "{(p, n) succ_rel (a # b # list). p ref} =
                 {(a, Some b)} {(p, n) succ_rel (b # list). p ref}"
    using assms(1by auto
  moreover have "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
  moreover have "{(i, n). i = oid (ref, n) succ_rel (a # b # list)} =
                 {(i, n). i = oid (ref, n) succ_rel (b # list)}"
    using assms(1by auto
  ultimately show ?thesis by simp
next
  case False
  then show ?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)
  moreover from this have "{(p, n) succ_rel (ref # list). p ref} = succ_rel list"
    using assms succ_rel_rem_head by (metis (mono_tags, lifting))
  moreover have "{(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
    moreover have "{(ref, n)} {(i, n) succ_rel (ref # list). i = ref}"
      by (simp add: ref_in_rel)
    ultimately show ?thesis by blast
  qed
  moreover have "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
  ultimately have "insert_alt (succ_rel (ref # list)) (oid, ref) =
                   succ_rel list {(ref, Some oid)} {(oid, n)}"
    by simp
  moreover have "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
  ultimately show "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
  moreover have "insert_spec (a # b # list) (oid, Some ref) =
                 a # (insert_spec (b # list) (oid, Some ref))"
    using assms(2by 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(1by auto
  moreover have "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(2by auto
  ultimately show ?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
  then show "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
  then show "succ_rel (insert_spec (a # list) (oid, Some ref)) =
             insert_alt (succ_rel (a # list)) (oid, ref)"
  proof(cases "a = ref")
    case True
    then show ?thesis
      using succ_rel_insert_head distinct (a # list) by metis
  next
    case False
    hence "a ref" by simp
    moreover have "succ_rel (insert_spec list (oid, Some ref)) =
                   insert_alt (succ_rel list) (oid, ref)"
      using Cons.IH Cons.prems by auto
    ultimately show "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

textThe 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
  then show "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(1by blast
    moreover have "set (interp_ins xs) fst ` set xs"
      using interp_ins_subset snoc.prems(1by fastforce
    ultimately show "distinct (head # interp_ins xs)"
      using snoc.prems(2by auto
  qed
  obtain oid r where x_pair: "x = (oid, r)" by force
  then show "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)
    moreover have "... = insert_alt (succ_rel (head # interp_ins xs)) (oid, head)"
      by (simp add: IH)
    moreover have "... = succ_rel (insert_spec (head # interp_ins xs) (oid, Some head))"
      using distinct_list succ_rel_insert_Some by metis
    moreover have "... = succ_rel (head # (insert_spec (interp_ins xs) (oid, None)))"
      by auto
    moreover have "... = succ_rel (head # (interp_ins (xs @ [x])))"
      by (simp add: interp_ins_tail_unfold None x_pair)
    ultimately show ?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)
    moreover have "... = insert_alt (succ_rel (head # interp_ins xs)) (oid, ref)"
      by (simp add: IH)
    moreover have "... = succ_rel (insert_spec (head # interp_ins xs) (oid, Some ref))"
      using distinct_list succ_rel_insert_Some by metis
    moreover have "... = succ_rel (head # (insert_spec (interp_ins xs) (oid, Some ref)))"
      using ref head by auto
    moreover have "... = succ_rel (head # (interp_ins (xs @ [x])))"
      by (simp add: interp_ins_tail_unfold Some x_pair)
    ultimately show ?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.


definition list_order :: "('oid::{linorder} × 'oid option) list ==> 'oid ==> 'oid ==> bool" where
  "list_order ops x y xs ys zs. interp_ins ops = xs @ [x] @ ys @ [y] @ zs"

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 where 1"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 where 2"interp_ins op_list = yxs@y#(yys@[z]@yzs)"
    using assms by (auto simp add: list_order_def interp_ins_def)
  have 3"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 1by auto
  hence "interp_ins op_list = xxs@[x]@xys@[y]@yys@[z]@yzs"
    using 1 2 3 by 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
  then have 1"interp_ins ops = insert_spec (interp_ins before) (oid, ref)"
    by (simp add: interp_ins_tail_unfold)
  then show "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)"
      using 1 Nil.prems(3by simp
    then show ?thesis by blast
  next
    case (Some a)
    then show ?thesis
    proof(cases "a set (interp_ins before)")
      case True
      then obtain 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"
        using 1 Nil.prems(3by auto
      then show ?thesis by blast
    next
      case False
      hence "interp_ins ops = (interp_ins rest) @ [] @ []"
        using insert_spec_nonex 1 Nil.prems(3) Some by simp
      then show ?thesis by blast
    qed
  qed
next
  case (snoc oper op_list)
  then have "insert_ops ((before @ (oid, ref) # op_list) @ [oper])"
    and "insert_ops ((before @ op_list) @ [oper])"
    by auto
  then have ops1: "insert_ops (before @ op_list)"
    and ops2: "insert_ops (before @ (oid, ref) # op_list)"
    using insert_ops_appendD by blast+
  then obtain 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
  then show "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)
    moreover have "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)
    ultimately show ?thesis
      using snoc.prems(3) snoc.prems(4by blast
  next
    case (Some r)
    then have 1"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)
    have 2"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
    then show "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)
      moreover have "insert_spec (xs @ zs) (i2, Some r) = (insert_spec xs (i2, Some r)) @ zs"
        by (meson r_xs insert_first_part)
      ultimately show ?thesis
        using 1 2 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+
      moreover from 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)
      moreover have "insert_spec (xs @ zs) (i2, Some r) = xs @ zs"
        by (simp add: Some calculation(1) calculation(2))
      ultimately show ?thesis
        using 1 2 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+
      moreover from 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)
      moreover have "insert_spec (xs @ zs) (i2, Some r) = xs @ (insert_spec zs (i2, Some r))"
        by (simp add: r_zs calculation(1) insert_second_part)
      ultimately show ?thesis
        using 1 2 oper = (i2, r2) snoc.prems by auto
    next
      case r_nonex
      then have "insert_spec (xs @ ys @ zs) (i2, Some r) = xs @ ys @ zs"
        by simp
      moreover have "insert_spec (xs @ zs) (i2, Some r) = xs @ zs"
        using r_nonex by simp
      ultimately show ?thesis
        using 1 2 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
  then show "length A length []" by simp
next
  case (Cons a B)
  then show "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
    then show "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
    then show "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)
  moreover from this have "card (set A) = card (set B)"
    using assms by (simp add: distinct_card le_antisym)
  ultimately show "set A = set B"
    using assms(1by (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
  then show "e. e set [] e set ys"
    by simp
next
  case (Cons a xs)
  then show "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)
      moreover have "set (remove1 a ys) set xs"
        using Cons.prems by auto
      ultimately show ?thesis
        by (meson Cons.IH Cons.prems distinct.simps(2) distinct_remove1)
    qed
    moreover have "set ys - {a} set xs"
      using Cons.prems(2by auto
    ultimately show "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
    then show "e. e set (a # xs) e set ys"
      by auto
  qed
qed

lemma app_length_lt_exists:
  assumes "xsa @ zsa = xs @ ys"
    and "length xsa length xs"
  shows "xsa @ (drop (length xsa) xs) = xs"
  using assms by (induction xsa arbitrary: xs zsa ys, simp,
      metis append_eq_append_conv_if append_take_drop_id)

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)
  then show "list_order xa x y"
  proof(cases "length xa - length A")
    case 0
    hence "set A = set xa"
      using set_subset_length_eq less.prems(3distinct 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)
    then show "list_order xa x y" 
      using less.prems(4by blast
  next
    case (Suc nat)
    then obtain e where "e set xa" and "e set A"
      using length_diff_Suc_exists distinct A distinct xa less.prems(3by 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
      moreover have "insert_ops (remove1 e xa)"
        by (simp add: insert_ops_remove1 less.prems(2))
      moreover have "set A set (remove1 e xa)"
        by (metis (no_types, lifting) e set A in_set_remove1 less.prems(3) rev_subsetD subsetI)
      ultimately show ?thesis
        by (simp add: Suc less.IH less.prems(1) less.prems(4))
    qed
    then obtain xs ys zs where "interp_ins (remove1 e xa) = xs @ x # ys @ y # zs"
      using list_order_def by fastforce
    moreover obtain oid ref where e_pair: "e = (oid, ref)"
      by fastforce
    moreover obtain 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)
    moreover from this have "insert_ops (ps @ ss)" and "insert_ops (ps @ e # ss)"
      using xa_split less.prems(2by (metis append_Cons append_Nil insert_ops_remove1, auto)
    then obtain 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
    moreover have xsa_zsa: "xsa @ zsa = xs @ x # ys @ y # zs"
      using interp_ins_def remove1_append calculation xa_split by auto
    then show "list_order xa x y"
    proof(cases "length xsa length xs")
      case True
      then obtain 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
      then show "list_order xa x y"
        using list_order_def by blast
    next
      case False
      then show "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)
        then obtain us where "xsa @ us = xs @ x # ys"
          using app_length_lt_exists True by blast
        moreover from 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
        moreover have "us @ y # zs = zsa"
          by (metis True xsa_zsa1 append_eq_append_conv_if append_eq_conv_conj calculation(1))
        ultimately have "interp_ins xa = xs @ [x] @
              ((drop (Suc (length xs)) xsa) @ ysa @ us) @ [y] @ zs"
          by (simp add: e_pair interp_xa xa_split)
        then show "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
        moreover have "(xs @ x # ys @ [y]) @ zs = xsa @ zsa"
          by (simp add: xsa_zsa)
        ultimately obtain 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
        then show "list_order xa x y"
          using list_order_def by blast
      qed
    qed
  qed
qed


end

Messung V0.5 in Prozent
C=82 H=95 G=88

¤ 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.0.38Bemerkung:  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.