Theory Collections.SetGA
section ‹\isaheader{Generic Algorithms for Sets}›
theory SetGA
imports "../spec/SetSpec" SetIteratorCollectionsGA
begin
text_raw ‹\label{thy:SetGA}›
subsection ‹Generic Set Algorithms›
locale g_set_xx_defs_loc = 
  s1: StdSetDefs ops1 + s2: StdSetDefs ops2
  for ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
begin
  definition "g_copy s ≡ s1.iterate s s2.ins_dj (s2.empty ())"
  definition "g_filter P s1 ≡ s1.iterate s1 
    (λx σ. if P x then s2.ins_dj x σ else σ) 
    (s2.empty ())"
  definition "g_union s1 s2 ≡ s1.iterate s1 s2.ins s2"
  definition "g_diff s1 s2 ≡ s2.iterate s2 s1.delete s1"
  definition g_union_list where
    "g_union_list l =
      foldl (λs s'. g_union s' s) (s2.empty ()) l"
  definition "g_union_dj s1 s2 ≡ s1.iterate s1 s2.ins_dj s2"
  definition "g_disjoint_witness s1 s2 ≡
    s1.sel s1 (λx. s2.memb x s2)"
  definition "g_disjoint s1 s2 ≡
    s1.ball s1 (λx. ¬s2.memb x s2)"
end
locale g_set_xx_loc = g_set_xx_defs_loc ops1 ops2 +
  s1: StdSet ops1 + s2: StdSet ops2
  for ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
begin
  lemma g_copy_alt: 
    "g_copy s = iterate_to_set s2.empty s2.ins_dj (s1.iteratei s)"
    unfolding iterate_to_set_alt_def g_copy_def ..
  lemma g_copy_impl: "set_copy s1.α s1.invar s2.α s2.invar g_copy" 
  proof -
    have LIS: 
      "set_ins_dj s2.α s2.invar s2.ins_dj" 
      "set_empty s2.α s2.invar s2.empty"
      by unfold_locales
    from iterate_to_set_correct[OF LIS s1.iteratei_correct]
    show ?thesis
      apply unfold_locales
      unfolding g_copy_alt
      by simp_all
  qed
  lemma g_filter_impl: "set_filter s1.α s1.invar s2.α s2.invar g_filter"
  proof
    fix s P
    assume "s1.invar s"
    hence "s2.α (g_filter P s) = {e ∈ s1.α s. P e} ∧
      s2.invar (g_filter P s)" (is "?G1 ∧ ?G2")
      unfolding g_filter_def
      apply (rule_tac I="λit σ. s2.invar σ ∧ s2.α σ = {e ∈ it. P e}" 
        in s1.iterate_rule_insert_P)
      by (auto simp add: s2.empty_correct s2.ins_dj_correct)
    thus ?G1 ?G2 by auto
  qed
  lemma g_union_alt: 
    "g_union s1 s2 = iterate_add_to_set s2 s2.ins (s1.iteratei s1)"
    unfolding iterate_add_to_set_def g_union_def ..
  lemma g_diff_alt:
    "g_diff s1 s2 = iterate_diff_set s1 s1.delete (s2.iteratei s2)"
    unfolding g_diff_def iterate_diff_set_def ..
  lemma g_union_impl:
    "set_union s1.α s1.invar s2.α s2.invar s2.α s2.invar g_union"
  proof -
    have LIS: "set_ins s2.α s2.invar s2.ins" by unfold_locales
    from iterate_add_to_set_correct[OF LIS _ s1.iteratei_correct]
    show ?thesis
      apply unfold_locales
      unfolding g_union_alt
      by simp_all
  qed
  lemma g_diff_impl:
    "set_diff s1.α s1.invar s2.α s2.invar g_diff"
  proof -
    have LIS: "set_delete s1.α s1.invar s1.delete" by unfold_locales
    from iterate_diff_correct[OF LIS _ s2.iteratei_correct]
    show ?thesis
      apply unfold_locales
      unfolding g_diff_alt
      by simp_all
  qed
  lemma g_union_list_impl:
    shows "set_union_list s1.α s1.invar s2.α s2.invar g_union_list"
  proof
    fix l
    note correct = s2.empty_correct set_union.union_correct[OF g_union_impl]
    assume "∀s1∈set l. s1.invar s1"
    hence aux: "⋀s. s2.invar s ⟹
           s2.α (foldl (λs s'. g_union s' s) s l) 
           = ⋃{s1.α s1 |s1. s1 ∈ set l} ∪ s2.α s ∧
           s2.invar (foldl (λs s'. g_union s' s) s l)"
      by (induct l) (auto simp add: correct)
    from aux [of "s2.empty ()"]
    show "s2.α (g_union_list l) = ⋃{s1.α s1 |s1. s1 ∈ set l}"
         "s2.invar (g_union_list l)"
      unfolding g_union_list_def
      by (simp_all add: correct)
  qed
  lemma g_union_dj_impl:
    "set_union_dj s1.α s1.invar s2.α s2.invar s2.α s2.invar g_union_dj"
  proof
    fix s1 s2
    assume I: 
      "s1.invar s1" 
      "s2.invar s2"
    assume DJ: "s1.α s1 ∩ s2.α s2 = {}"
    have "s2.α (g_union_dj s1 s2) 
      = s1.α s1 ∪ s2.α s2
      ∧ s2.invar (g_union_dj s1 s2)" (is "?G1 ∧ ?G2")
      unfolding g_union_dj_def
      apply (rule_tac I="λit σ. s2.invar σ ∧ s2.α σ = it ∪ s2.α s2" 
        in s1.iterate_rule_insert_P)
      using DJ
      apply (simp_all add: I)
      apply (subgoal_tac "x∉s2.α σ")
      apply (simp add: s2.ins_dj_correct I)
      apply auto
      done
    thus ?G1 ?G2 by auto
  qed
  lemma g_disjoint_witness_impl: 
    "set_disjoint_witness s1.α s1.invar s2.α s2.invar g_disjoint_witness"
  proof -
    show ?thesis
      apply unfold_locales
      unfolding g_disjoint_witness_def
      by (auto dest: s1.sel'_noneD s1.sel'_someD simp: s2.memb_correct)
  qed
  lemma g_disjoint_impl: 
    "set_disjoint s1.α s1.invar s2.α s2.invar g_disjoint"
  proof -
    show ?thesis
      apply unfold_locales
      unfolding g_disjoint_def
      by (auto simp: s2.memb_correct s1.ball_correct)
  qed
end
sublocale g_set_xx_loc < 
  set_copy s1.α s1.invar s2.α s2.invar g_copy by (rule g_copy_impl)
sublocale g_set_xx_loc < 
  set_filter s1.α s1.invar s2.α s2.invar g_filter by (rule g_filter_impl)
sublocale g_set_xx_loc < 
  set_union s1.α s1.invar s2.α s2.invar s2.α s2.invar g_union 
  by (rule g_union_impl)
sublocale g_set_xx_loc < 
  set_union_dj s1.α s1.invar s2.α s2.invar s2.α s2.invar g_union_dj 
  by (rule g_union_dj_impl)
sublocale g_set_xx_loc < 
  set_diff s1.α s1.invar s2.α s2.invar g_diff 
  by (rule g_diff_impl)
sublocale g_set_xx_loc < 
  set_disjoint_witness s1.α s1.invar s2.α s2.invar g_disjoint_witness
  by (rule g_disjoint_witness_impl)
sublocale g_set_xx_loc < 
  set_disjoint s1.α s1.invar s2.α s2.invar g_disjoint by (rule g_disjoint_impl)
locale g_set_xxx_defs_loc =
  s1: StdSetDefs ops1 +
  s2: StdSetDefs ops2 +
  s3: StdSetDefs ops3
  for ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
  and ops3 :: "('x,'s3,'more3) set_ops_scheme"
begin
  definition "g_inter s1 s2 ≡
    s1.iterate s1 (λx s. if s2.memb x s2 then s3.ins_dj x s else s) 
      (s3.empty ())"
end
locale g_set_xxx_loc = g_set_xxx_defs_loc ops1 ops2 ops3 +
  s1: StdSet ops1 +
  s2: StdSet ops2 +
  s3: StdSet ops3
  for ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
  and ops3 :: "('x,'s3,'more3) set_ops_scheme"
begin
  lemma g_inter_impl: "set_inter s1.α s1.invar s2.α s2.invar s3.α s3.invar
    g_inter"
  proof
    fix s1 s2
    assume I: 
      "s1.invar s1" 
      "s2.invar s2"
    have "s3.α (g_inter s1 s2) = s1.α s1 ∩ s2.α s2 ∧ s3.invar (g_inter s1 s2)"
      unfolding g_inter_def
      apply (rule_tac I="λit σ. s3.α σ = it ∩ s2.α s2 ∧ s3.invar σ" 
        in s1.iterate_rule_insert_P) 
      apply (simp_all add: I s3.empty_correct s3.ins_dj_correct s2.memb_correct)
      done
    thus "s3.α (g_inter s1 s2) = s1.α s1 ∩ s2.α s2" 
      and "s3.invar (g_inter s1 s2)" by auto
  qed
end    
sublocale g_set_xxx_loc 
  < set_inter s1.α s1.invar s2.α s2.invar s3.α s3.invar g_inter
  by (rule g_inter_impl)
locale g_set_xy_defs_loc = 
  s1: StdSet ops1 + s2: StdSet ops2
  for ops1 :: "('x1,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x2,'s2,'more2) set_ops_scheme"
begin
  definition "g_image_filter f s ≡ 
    s1.iterate s 
      (λx res. case f x of Some v ⇒ s2.ins v res | _ ⇒ res) 
      (s2.empty ())"
  definition "g_image f s ≡ 
    s1.iterate s (λx res. s2.ins (f x) res) (s2.empty ())"
  definition "g_inj_image_filter f s ≡ 
    s1.iterate s 
      (λx res. case f x of Some v ⇒ s2.ins_dj v res | _ ⇒ res) 
      (s2.empty ())"
  definition "g_inj_image f s ≡ 
    s1.iterate s (λx res. s2.ins_dj (f x) res) (s2.empty ())"
end
locale g_set_xy_loc = g_set_xy_defs_loc ops1 ops2 +
  s1: StdSet ops1 + s2: StdSet ops2
  for ops1 :: "('x1,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x2,'s2,'more2) set_ops_scheme"
begin
  lemma g_image_filter_impl: 
    "set_image_filter s1.α s1.invar s2.α s2.invar g_image_filter"
  proof
    fix f s
    assume I: "s1.invar s"
    have A: "g_image_filter f s == 
         iterate_to_set s2.empty s2.ins 
           (set_iterator_image_filter f (s1.iteratei s))"
      unfolding g_image_filter_def 
        iterate_to_set_alt_def set_iterator_image_filter_def
      by simp
    
    have ins: "set_ins s2.α s2.invar s2.ins"
      and emp: "set_empty s2.α s2.invar s2.empty" by unfold_locales
    from iterate_image_filter_to_set_correct[OF ins emp s1.iteratei_correct]
    show "s2.α (g_image_filter f s) =
          {b. ∃a∈s1.α s. f a = Some b}"
         "s2.invar (g_image_filter f s)"
      unfolding A using I by auto
  qed
  lemma g_image_alt: "g_image f s = g_image_filter (Some o f) s"
    unfolding g_image_def g_image_filter_def
    by auto
  lemma g_image_impl: "set_image s1.α s1.invar s2.α s2.invar g_image" 
  proof -
    interpret set_image_filter s1.α s1.invar s2.α s2.invar g_image_filter 
      by (rule g_image_filter_impl)
    show ?thesis
      apply unfold_locales
      unfolding g_image_alt
      by (auto simp add: image_filter_correct)
  qed
  lemma g_inj_image_filter_impl: 
    "set_inj_image_filter s1.α s1.invar s2.α s2.invar g_inj_image_filter"
  proof
    fix f::"'x1 ⇀ 'x2" and s
    assume I: "s1.invar s" and INJ: "inj_on f (s1.α s ∩ dom f)"
    have A: "g_inj_image_filter f s == 
         iterate_to_set s2.empty s2.ins_dj 
           (set_iterator_image_filter f (s1.iteratei s))"
      unfolding g_inj_image_filter_def 
        iterate_to_set_alt_def set_iterator_image_filter_def
      by simp
    
    have ins_dj: "set_ins_dj s2.α s2.invar s2.ins_dj"
      and emp: "set_empty s2.α s2.invar s2.empty" by unfold_locales
    from set_iterator_image_filter_correct[OF s1.iteratei_correct[OF I] INJ]
    have iti_s1_filter: "set_iterator 
      (set_iterator_image_filter f (s1.iteratei s))
      {y. ∃x. x ∈ s1.α s ∧ f x = Some y}"
      by simp
    from iterate_to_set_correct[OF ins_dj emp, OF iti_s1_filter]
    show "s2.α (g_inj_image_filter f s) =
          {b. ∃a∈s1.α s. f a = Some b}"
         "s2.invar (g_inj_image_filter f s)"
      unfolding A by auto
  qed
  lemma g_inj_image_alt: "g_inj_image f s = g_inj_image_filter (Some o f) s"
    unfolding g_inj_image_def g_inj_image_filter_def
    by auto
  lemma g_inj_image_impl: 
    "set_inj_image s1.α s1.invar s2.α s2.invar g_inj_image" 
  proof -
    interpret set_inj_image_filter 
      s1.α s1.invar s2.α s2.invar g_inj_image_filter 
      by (rule g_inj_image_filter_impl)
    have AUX: "⋀S f. inj_on f S ⟹ inj_on (Some ∘ f) (S ∩ dom (Some ∘ f))"
      by (auto intro!: inj_onI dest: inj_onD)
      
    show ?thesis
      apply unfold_locales
      unfolding g_inj_image_alt
      by (auto simp add: inj_image_filter_correct AUX)
  qed
end
sublocale g_set_xy_loc < set_image_filter s1.α s1.invar s2.α s2.invar 
  g_image_filter by (rule g_image_filter_impl)
sublocale g_set_xy_loc < set_image s1.α s1.invar s2.α s2.invar 
  g_image by (rule g_image_impl)
sublocale g_set_xy_loc < set_inj_image s1.α s1.invar s2.α s2.invar 
  g_inj_image by (rule g_inj_image_impl)
locale g_set_xyy_defs_loc = 
  s0: StdSetDefs ops0 + 
  g_set_xx_defs_loc ops1 ops2
  for ops0 :: "('x0,'s0,'more0) set_ops_scheme"
  and ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
begin
  definition g_Union_image
    :: "('x0 ⇒ 's1) ⇒ 's0 ⇒ 's2"
    where "g_Union_image f S 
    == s0.iterate S (λx res. g_union (f x) res) (s2.empty ())"
end
locale g_set_xyy_loc = g_set_xyy_defs_loc ops0 ops1 ops2 +
  s0: StdSet ops0 + 
  g_set_xx_loc ops1 ops2
  for ops0 :: "('x0,'s0,'more0) set_ops_scheme"
  and ops1 :: "('x,'s1,'more1) set_ops_scheme"
  and ops2 :: "('x,'s2,'more2) set_ops_scheme"
begin
  lemma g_Union_image_impl:
    "set_Union_image s0.α s0.invar s1.α s1.invar s2.α s2.invar g_Union_image"
  proof -
    {
      fix s f
      have "⟦s0.invar s; ⋀x. x ∈ s0.α s ⟹ s1.invar (f x)⟧ ⟹ 
        s2.α (g_Union_image f s) = ⋃(s1.α ` f ` s0.α s) 
        ∧ s2.invar (g_Union_image f s)"
        apply (unfold g_Union_image_def)
        apply (rule_tac I="λit res. s2.invar res 
          ∧ s2.α res = ⋃(s1.α`f`(s0.α s - it))" in s0.iterate_rule_P)
        apply (fastforce simp add: s2.empty_correct union_correct)+
        done
    }
    thus ?thesis
      apply unfold_locales
      apply auto
      done
  qed
end
sublocale g_set_xyy_loc < 
  set_Union_image s0.α s0.invar s1.α s1.invar s2.α s2.invar g_Union_image
  by (rule g_Union_image_impl)
subsection ‹Default Set Operations›