Theory Watched_Literals_All_Literals

theory Watched_Literals_All_Literals
imports Watched_Literals_Clauses
begin

chapter Set of all literals

type_synonym ann_lits_l = (nat, nat) ann_lits
type_synonym clauses_to_update_ll = nat list


section Refinement

subsection Set of all literals of the problem

definition all_lits_of_mm :: 'a clauses  'a literal multiset where
all_lits_of_mm Ls = Pos `# (atm_of `# (# Ls)) + Neg `# (atm_of `# (# Ls))

lemma all_lits_of_mm_empty[simp]: all_lits_of_mm {#} = {#}
  by (auto simp: all_lits_of_mm_def)
lemma in_all_lits_of_mm_ain_atms_of_iff:
  L ∈# all_lits_of_mm N  atm_of L  atms_of_mm N
  by (cases L) (auto simp: all_lits_of_mm_def atms_of_ms_def atms_of_def)

lemma all_lits_of_mm_union:
  all_lits_of_mm (M + N) = all_lits_of_mm M + all_lits_of_mm N
  unfolding all_lits_of_mm_def by auto

definition all_lits_of_m :: 'a clause  'a literal multiset where
  all_lits_of_m Ls = Pos `# (atm_of `# Ls) + Neg `# (atm_of `# Ls)

lemma all_lits_of_m_empty[simp]: all_lits_of_m {#} = {#}
  by (auto simp: all_lits_of_m_def)

lemma all_lits_of_m_empty_iff[iff]: all_lits_of_m A = {#}  A = {#}
  by (cases A) (auto simp: all_lits_of_m_def)

lemma in_all_lits_of_m_ain_atms_of_iff: L ∈# all_lits_of_m N  atm_of L  atms_of N
  by (cases L) (auto simp: all_lits_of_m_def atms_of_ms_def atms_of_def)

lemma in_clause_in_all_lits_of_m: x ∈# C  x ∈# all_lits_of_m C
  using atm_of_lit_in_atms_of in_all_lits_of_m_ain_atms_of_iff by blast

lemma all_lits_of_mm_add_mset:
  all_lits_of_mm (add_mset C N) = (all_lits_of_m C) + (all_lits_of_mm N)
  by (auto simp: all_lits_of_mm_def all_lits_of_m_def)

lemma all_lits_of_m_add_mset:
  all_lits_of_m (add_mset L C) = add_mset L (add_mset (-L) (all_lits_of_m C))
  by (cases L) (auto simp: all_lits_of_m_def)

lemma all_lits_of_m_union:
  all_lits_of_m (A + B) = all_lits_of_m A + all_lits_of_m B
  by (auto simp: all_lits_of_m_def)

lemma all_lits_of_m_mono:
  D ⊆# D'  all_lits_of_m D ⊆# all_lits_of_m D'
  by (auto elim!: mset_le_addE simp: all_lits_of_m_union)

lemma all_lits_of_m_diffD: x ∈# all_lits_of_m (D - D')  x ∈# all_lits_of_m D
  by (auto simp: all_lits_of_m_def dest: in_diffD)


lemma in_all_lits_of_mm_uminusD: x2 ∈# all_lits_of_mm N  -x2 ∈# all_lits_of_mm N
  by (auto simp: all_lits_of_mm_def)

lemma in_all_lits_of_mm_uminus_iff: -x2 ∈# all_lits_of_mm N  x2 ∈# all_lits_of_mm N
  by (cases x2) (auto simp: all_lits_of_mm_def)

lemma all_lits_of_mm_diffD:
  L ∈# all_lits_of_mm (A - B)  L ∈# all_lits_of_mm A
  apply (induction A arbitrary: B)
  subgoal by auto
  subgoal for a A' B
    by (cases a ∈# B)
      (fastforce dest!: multi_member_split[of a B] simp: all_lits_of_mm_add_mset)+
  done

lemma all_lits_of_mm_mono:
  set_mset A  set_mset B  set_mset (all_lits_of_mm A)  set_mset (all_lits_of_mm B)
  by (auto simp: all_lits_of_mm_def)


section Conversion from set of atoms to set of literals

text We start in a context where we have an initial set of atoms. We later extend the locale to
  include a bound on the largest atom (in order to generate more efficient code).

context
  fixes 𝒜in :: 'v multiset
begin

text This is the completion of term𝒜in, containing the positive and the negation of every
  literal of term𝒜in:
definition all where all = poss 𝒜in + negs 𝒜in

lemma atms_of_ℒall_𝒜in: atms_of all = set_mset 𝒜in
  unfolding all_def by (auto simp: atms_of_def image_Un image_image)

definition is_ℒall :: 'v literal multiset  bool where
  is_ℒall S  set_mset all = set_mset S

definition literals_are_in_ℒin :: 'v clause  bool where
  literals_are_in_ℒin C  set_mset (all_lits_of_m C)  set_mset all

lemma literals_are_in_ℒin_empty[simp]: literals_are_in_ℒin {#}
  by (auto simp: literals_are_in_ℒin_def)

lemma in_ℒall_atm_of_in_atms_of_iff: x ∈# all  atm_of x  atms_of all
  by (cases x) (auto simp: all_def atms_of_def atm_of_eq_atm_of image_Un image_image)

lemma literals_are_in_ℒin_add_mset:
  literals_are_in_ℒin (add_mset L A)  literals_are_in_ℒin A  L ∈# all
  by (auto simp: literals_are_in_ℒin_def all_lits_of_m_add_mset in_ℒall_atm_of_in_atms_of_iff)

lemma literals_are_in_ℒin_mono:
  assumes N: literals_are_in_ℒin D' and D: D ⊆# D'
  shows literals_are_in_ℒin D
proof -
  have set_mset (all_lits_of_m D)  set_mset (all_lits_of_m D')
    using D by (auto simp: in_all_lits_of_m_ain_atms_of_iff atm_iff_pos_or_neg_lit)
  then show ?thesis
     using N unfolding literals_are_in_ℒin_def by fast
qed

lemma literals_are_in_ℒin_sub:
  literals_are_in_ℒin y  literals_are_in_ℒin (y - z)
  using literals_are_in_ℒin_mono[of y y - z] by auto

lemma all_lits_of_m_subset_all_lits_of_mmD:
  a ∈# b  set_mset (all_lits_of_m a)  set_mset (all_lits_of_mm b)
  by (auto simp: all_lits_of_m_def all_lits_of_mm_def)

lemma all_lits_of_m_remdups_mset:
  set_mset (all_lits_of_m (remdups_mset N)) = set_mset (all_lits_of_m N)
  by (auto simp: all_lits_of_m_def)

lemma literals_are_in_ℒin_remdups[simp]:
  literals_are_in_ℒin (remdups_mset N) = literals_are_in_ℒin N
  by (auto simp: literals_are_in_ℒin_def all_lits_of_m_remdups_mset)

lemma uminus_𝒜in_iff: - L ∈# all  L ∈# all
  by (simp add: in_ℒall_atm_of_in_atms_of_iff)

definition literals_are_in_ℒin_mm :: 'v clauses  bool where
  literals_are_in_ℒin_mm C  set_mset (all_lits_of_mm C)  set_mset all

lemma literals_are_in_ℒin_mm_add_msetD:
  literals_are_in_ℒin_mm (add_mset C N)  L ∈# C  L ∈# all
  by (auto simp: literals_are_in_ℒin_mm_def all_lits_of_mm_add_mset
      all_lits_of_m_add_mset
    dest!: multi_member_split)

lemma literals_are_in_ℒin_mm_add_mset:
  literals_are_in_ℒin_mm (add_mset C N) 
    literals_are_in_ℒin_mm N  literals_are_in_ℒin C
  unfolding literals_are_in_ℒin_mm_def  literals_are_in_ℒin_def
  by (auto simp: all_lits_of_mm_add_mset)

definition literals_are_in_ℒin_trail :: ('v, 'mark) ann_lits  bool where
  literals_are_in_ℒin_trail M  set_mset (lit_of `# mset M)  set_mset all

lemma literals_are_in_ℒin_trail_in_lits_of_l:
  literals_are_in_ℒin_trail M  a  lits_of_l M  a ∈# all
  by (auto simp: literals_are_in_ℒin_trail_def lits_of_def)

lemma literals_are_in_ℒin_trail_uminus_in_lits_of_l:
  literals_are_in_ℒin_trail M  -a  lits_of_l M  a ∈# all
  by (auto simp: literals_are_in_ℒin_trail_def lits_of_def uminus_lit_swap uminus_𝒜in_iff)

lemma literals_are_in_ℒin_trail_uminus_in_lits_of_l_atms:
  literals_are_in_ℒin_trail M  -a  lits_of_l M  atm_of a ∈# 𝒜in
  using literals_are_in_ℒin_trail_uminus_in_lits_of_l[of M a]
  unfolding in_ℒall_atm_of_in_atms_of_iff[symmetric] atms_of_ℒall_𝒜in[symmetric]
  .
end

lemma isasat_input_ops_ℒall_empty[simp]:
  all {#} = {#}
  unfolding all_def
  by auto

lemma all_atm_of_all_lits_of_mm: set_mset (all (atm_of `#  all_lits_of_mm A)) = set_mset (all_lits_of_mm A)
  apply (auto simp: all_def in_all_lits_of_mm_ain_atms_of_iff)
  by (metis (no_types, lifting) image_iff in_all_lits_of_mm_ain_atms_of_iff literal.exhaust_sel)


definition all_lits :: ('a, 'v literal list × 'b) fmap  'v literal multiset multiset 
   'v literal multiset where
  all_lits S NUE = all_lits_of_mm ((λC. mset (fst C)) `# ran_m S + NUE)

lemma all_lits_alt_def:
  all_lits S NUE = all_lits_of_mm (mset `# ran_mf S + NUE)
  unfolding all_lits_def
  by auto

lemma all_lits_alt_def2:
  all_lits S (NUE + NUS + N0S) = all_lits_of_mm (mset `# ran_mf S + NUE + NUS + N0S)
  all_lits S (NUE + NUS + N0S) = all_lits_of_mm ((λC. mset (fst C)) `# ran_m S + NUE + NUS + N0S)
  unfolding all_lits_def
  by (auto simp: ac_simps)

lemma literals_are_in_ℒin_mm_in_ℒall:
  assumes
    N1: literals_are_in_ℒin_mm 𝒜 (mset `# ran_mf xs) and
    i_xs: i ∈# dom_m xs and j_xs: j < length (xs  i)
  shows xs  i ! j ∈# all 𝒜
proof -
  have xs  i ∈# ran_mf xs
    using i_xs by auto
  then have xs  i ! j  set_mset (all_lits_of_mm (mset `# ran_mf xs))
    using j_xs by (auto simp: in_all_lits_of_mm_ain_atms_of_iff atms_of_ms_def Bex_def
      intro!: exI[of _ xs  i])
  then show ?thesis
    using N1 unfolding literals_are_in_ℒin_mm_def by blast
qed


lemma literals_are_in_ℒin_trail_in_lits_of_l_atms:
  literals_are_in_ℒin_trail 𝒜in M  a  lits_of_l M  atm_of a ∈# 𝒜in
  using literals_are_in_ℒin_trail_in_lits_of_l[of 𝒜in M a]
  unfolding in_ℒall_atm_of_in_atms_of_iff[symmetric] atms_of_ℒall_𝒜in[symmetric]
  .

lemma literals_are_in_ℒin_trail_Cons:
  literals_are_in_ℒin_trail 𝒜in (L # M) 
      literals_are_in_ℒin_trail 𝒜in M  lit_of L ∈# all 𝒜in
  by (auto simp: literals_are_in_ℒin_trail_def)

lemma literals_are_in_ℒin_trail_empty[simp]:
  literals_are_in_ℒin_trail 𝒜 []
  by (auto simp: literals_are_in_ℒin_trail_def)

lemma literals_are_in_ℒin_trail_lit_of_mset:
  literals_are_in_ℒin_trail 𝒜 M = literals_are_in_ℒin 𝒜 (lit_of `# mset M)
  by (induction M) (auto simp: literals_are_in_ℒin_add_mset literals_are_in_ℒin_trail_Cons)

lemma literals_are_in_ℒin_in_mset_ℒall:
  literals_are_in_ℒin 𝒜 C  L ∈# C  L ∈# all 𝒜
  unfolding literals_are_in_ℒin_def
  by (auto dest!: multi_member_split simp: all_lits_of_m_add_mset)

lemma literals_are_in_ℒin_in_ℒall:
  assumes
    N1: literals_are_in_ℒin 𝒜 (mset xs) and
    i_xs: i < length xs
  shows xs ! i ∈# all 𝒜
  using literals_are_in_ℒin_in_mset_ℒall[of 𝒜 mset xs xs!i] assms by auto

lemma is_ℒall_ℒall_rewrite[simp]:
  is_ℒall 𝒜 (all_lits_of_mm 𝒜') 
    set_mset (all (atm_of `# all_lits_of_mm 𝒜')) = set_mset (all 𝒜)
  using in_all_lits_of_mm_ain_atms_of_iff
  unfolding set_mset_set_mset_eq_iff is_ℒall_def Ball_def in_ℒall_atm_of_in_atms_of_iff
    in_all_lits_of_mm_ain_atms_of_iff atms_of_ℒall_𝒜in
  by (auto simp: in_all_lits_of_mm_ain_atms_of_iff)

lemma is_ℒall_alt_def: is_ℒall 𝒜 (all_lits_of_mm A)  atms_of (all 𝒜) = atms_of_mm A
  unfolding set_mset_set_mset_eq_iff is_ℒall_def Ball_def in_ℒall_atm_of_in_atms_of_iff
    in_all_lits_of_mm_ain_atms_of_iff
  by auto (metis literal.sel(2))+

lemma in_ℒall_atm_of_𝒜in: L ∈# all 𝒜in  atm_of L ∈# 𝒜in
  by (cases L) (auto simp: all_def)

lemma literals_are_in_ℒin_alt_def:
  literals_are_in_ℒin 𝒜 S  atms_of S  atms_of (all 𝒜)
  apply (auto simp: literals_are_in_ℒin_def all_lits_of_mm_union lits_of_def
       in_all_lits_of_m_ain_atms_of_iff in_all_lits_of_mm_ain_atms_of_iff atms_of_ℒall_𝒜in
       atm_of_eq_atm_of uminus_𝒜in_iff subset_iff in_ℒall_atm_of_𝒜in)
  apply (auto simp: atms_of_def)
  done

lemma literals_are_in_ℒin_trail_atm_of:
  literals_are_in_ℒin_trail 𝒜in M  atm_of ` lits_of_l M  set_mset 𝒜in
  apply (rule iffI)
  subgoal by (auto dest: literals_are_in_ℒin_trail_in_lits_of_l_atms)
  subgoal by (fastforce simp: literals_are_in_ℒin_trail_def lits_of_def in_ℒall_atm_of_𝒜in)
  done

lemma literals_are_in_ℒin_poss_remdups_mset:
  literals_are_in_ℒin 𝒜in (poss (remdups_mset (atm_of `# C)))  literals_are_in_ℒin 𝒜in C
  by (induction C)
    (auto simp: literals_are_in_ℒin_add_mset in_ℒall_atm_of_in_atms_of_iff atm_of_eq_atm_of
      dest!: multi_member_split)

lemma literals_are_in_ℒin_negs_remdups_mset:
  literals_are_in_ℒin 𝒜in (negs (remdups_mset (atm_of `# C)))  literals_are_in_ℒin 𝒜in C
  by (induction C)
    (auto simp: literals_are_in_ℒin_add_mset in_ℒall_atm_of_in_atms_of_iff atm_of_eq_atm_of
      dest!: multi_member_split)

lemma all_atm_of_all_lits_of_m:
   set_mset (all (atm_of `# all_lits_of_m C)) = set_mset C  uminus ` set_mset C
  supply lit_eq_Neg_Pos_iff[iff]
  by (auto simp: all_def all_lits_of_m_def image_iff dest!: multi_member_split)

lemma atm_of_all_lits_of_mm:
  set_mset (atm_of `# all_lits_of_mm bw) = atms_of_mm bw
  atm_of ` set_mset (all_lits_of_mm bw) = atms_of_mm bw
  using in_all_lits_of_mm_ain_atms_of_iff apply (auto simp: image_iff)
  by (metis (full_types) image_eqI literal.sel(1))+

lemma all_union:
   set_mset (all (A + B)) = set_mset (all  A)  set_mset (all  B)
  by (auto simp: all_def)

lemma all_cong:
  set_mset A = set_mset B  set_mset (all A) = set_mset (all B)
  by (auto simp: all_def)

lemma atms_of_ℒall_cong:
  set_mset 𝒜 = set_mset   atms_of (all 𝒜) = atms_of (all )
  unfolding all_def
  by auto

lemma is_ℒall_cong:
  set_mset 𝒜 = set_mset   is_ℒall 𝒜 =  is_ℒall 
  unfolding all_def is_ℒall_def
  by auto


text The definition is here to be shared later.
definition get_propagation_reason :: ('v, 'mark) ann_lits  'v literal  'mark option nres where
  get_propagation_reason M L = SPEC(λC. C  None  Propagated L (the C)  set M)


end