(*  Title:       Preliminaries for Abstract Splitting Architecture
    Author:      Jasmin Blanchette <j.c.blanchette at vu.nl>, 2018
*)

section \<open>Preliminaries for Abstract Splitting Architecture\<close>

theory Splitting_Preliminaries
  imports
    Ordered_Resolution_Prover.Clausal_Logic
begin

locale nonclausal_consequence_relation =
  fixes
    bot :: 'f and
    entails :: "'f set \<Rightarrow> 'f set \<Rightarrow> bool" (infix "\<Turnstile>" 50)
  assumes
    bot_implies_all: "{bot} \<Turnstile> N1" and
    subset_entailed: "N2 \<subseteq> N1 \<Longrightarrow> N1 \<Turnstile> N2" and
    all_formulas_entailed [intro]: "(\<forall>C \<in> N2. N1 \<Turnstile> {C}) \<Longrightarrow> N1 \<Turnstile> N2" and
    entails_trans [trans]: "N1 \<Turnstile> N2 \<Longrightarrow> N2 \<Turnstile> N3 \<Longrightarrow> N1 \<Turnstile> N3" and
    nothing_nimplies_bot:  "\<not> {} \<Turnstile> {bot}"
begin

lemma entail_iff_each: "N1 \<Turnstile> N2 \<longleftrightarrow> (\<forall>C \<in> N2. N1 \<Turnstile> {C})"
  by (meson all_formulas_entailed bot.extremum entails_trans insert_subsetI subset_entailed)

lemma entails_bigunion_iff: "N \<Turnstile> (\<Union>i \<in> I. M i) \<longleftrightarrow> (\<forall>i \<in> I. N \<Turnstile> M i)"
  by (smt UN_iff entail_iff_each)

end

locale clausal_consequence_relation = nonclausal_consequence_relation "{#}" +
  assumes
    entails_excluded_middle: "{} \<Turnstile> {{#Pos a, Neg a#}}" and
    entails_absurd: "{{#Pos a#}, {#Neg a#}} \<Turnstile> {C}" and
    entails_subclause: "C \<subseteq># D \<Longrightarrow> {C} \<Turnstile> {D}"
begin

lemma entails_absurd_lit: "{{#L#}, {#- L#}} \<Turnstile> {{#}}"
proof - (* generated by Sledgehammer *)
  have f1: "\<forall>l. if is_pos l then - l = Neg (atm_of l::'a) else - l = Pos (atm_of l)"
    by (simp add: uminus_literal_def)
  have "- L = Pos (atm_of L) \<longrightarrow> Neg (atm_of L) = - (- L)"
    by fastforce
  then have "- L = Pos (atm_of L) \<longrightarrow> {{#L#}, {#- L#}} \<Turnstile> {{#}}"
    by (metis (no_types) atm_of_eq_atm_of entails_absurd insert_commute)
  then show ?thesis
    using f1 by (metis (no_types) atm_of_eq_atm_of entails_absurd uminus_Neg)
qed

lemma entails_weaken_subclause_left:
  assumes stronger: "N \<union> {C1 + C2} \<Turnstile> C3"
  shows "N \<union> {C1} \<Turnstile> C3"
proof -
  have "N \<union> {C1} \<Turnstile> {C1}"
    by (simp add: subset_entailed)
  moreover have "{C1} \<Turnstile> {C1 + C2}"
    by (simp add: entails_subclause) 
  ultimately have "N \<union> {C1} \<Turnstile> {C1 + C2}"
    using entails_trans by blast

  hence "N \<union> {C1} \<Turnstile> N \<union> {C1 + C2}"
    by (metis Un_iff bot.extremum entail_iff_each insert_subset subset_entailed)
  thus "N \<union> {C1} \<Turnstile> C3"
    using entails_trans stronger by blast
qed

lemma entails_weaken_subclause_right:
  assumes stronger: "M \<Turnstile> N \<union> {C1}"
  shows "M \<Turnstile> N \<union> {C1 + C2}"
by (metis (no_types, opaque_lifting) Un_insert_right entail_iff_each entails_subclause entails_trans
    insert_iff mset_subset_eq_add_left stronger sup_bot.right_neutral)

definition entails_comp_sqcup :: "'a clause set \<Rightarrow> 'a clause set \<Rightarrow> bool" (infix "\<Turnstile>\<^sub>\<squnion>" 50) where
  "M \<Turnstile>\<^sub>\<squnion> CC \<longleftrightarrow> (\<forall>N D. N \<Turnstile> M \<longrightarrow> (\<forall>C \<in> CC. N \<union> {C} \<Turnstile> {D}) \<longrightarrow> N \<Turnstile> {D})"

lemma entails_comp_sqcup_trans:
  assumes
    mn: "M \<Turnstile> N" and
    ncc: "N \<Turnstile>\<^sub>\<squnion> CC"
  shows "M \<Turnstile>\<^sub>\<squnion> CC"
  unfolding entails_comp_sqcup_def
  by (clarify, rule ncc[unfolded entails_comp_sqcup_def, rule_format])
    (blast intro: entails_trans mn)+

definition is_propos :: "'a \<Rightarrow> bool" where
  "is_propos a \<longleftrightarrow> (\<forall>L \<in> {Pos a, Neg a}. \<forall>C. {{#L#} + C} \<Turnstile>\<^sub>\<squnion> {{#L#}, C})"

lemma is_propos_entails_comp_sqcup_excluded_middle:
  assumes prp: "is_propos a"
  shows "{} \<Turnstile>\<^sub>\<squnion> {{#Pos a#}, {#Neg a#}}"
  using prp[unfolded is_propos_def, rule_format, of "Pos a" "{#Neg a#}", simplified]
  by (metis (no_types) add_mset_commute entails_comp_sqcup_trans entails_excluded_middle)

end

locale abstraction_function = clausal_consequence_relation +
  fixes
    \<alpha> :: "'a clause \<Rightarrow> 'a literal set" and
    \<alpha>s  :: "'a clause set \<Rightarrow> 'a literal set"
  assumes
    \<alpha>_propos: "\<forall>L \<in> \<alpha> C. is_propos (atm_of L)" and
    \<alpha>s_def: "\<alpha>s N = {L. \<exists>C \<in> N. L \<in> \<alpha> C}" and
    \<alpha>_literal: "L \<in> \<alpha> C \<Longrightarrow> M \<union> (\<lambda>L. {#L#}) ` \<alpha>s N \<Turnstile> {{#L#}} \<Longrightarrow> M \<union> N \<Turnstile> {C}" and
    \<alpha>_clause: "M \<union> (\<lambda>L. {#L#}) ` \<alpha>s N \<Turnstile> {C} \<Longrightarrow> M \<union> N \<Turnstile> {C}"
begin

lemma \<alpha>_inter_imp_entails:
  assumes in_inter: "L \<in> \<alpha> C \<inter> \<alpha> D"
  shows "{C} \<Turnstile> {D}"
proof -
  have "L \<in> \<alpha> D"
    using in_inter by auto
  moreover have "(\<lambda>L. {#L#}) ` \<alpha>s {C} \<Turnstile> {{#L#}}"
    unfolding \<alpha>s_def using in_inter subset_entailed by auto
  ultimately show "{C} \<Turnstile> {D}"
    using \<alpha>_literal[of L D "{}" "{C}", simplified] by auto
qed

lemma \<alpha>_inconsistent:
  assumes l: "L \<in> \<alpha> C" and not_l: "- L \<in> \<alpha> D"
  shows "{C, D} \<Turnstile> {{#}}"
proof -
  have "{{#L#}, {#- L#}} \<subseteq> (\<lambda>L. {#L#}) ` \<alpha>s {C, D}"
    unfolding \<alpha>s_def using l not_l by auto
  hence "(\<lambda>L. {#L#}) ` \<alpha>s {C, D} \<Turnstile> {{#}}"
    using entails_absurd_lit by (metis (no_types) entails_trans subset_entailed)
  thus "{C, D} \<Turnstile> {{#}}"
    using \<alpha>_clause[of "{}" "{C, D}" "{#}", simplified] by blast
qed

end

end
