Theory Entailment_Lifting

theory Entailment_Lifting
  imports Abstract_Substitution.Based_Substitution_Lifting
begin

locale entailment =
  based: based_subst_update where base_subst = base_subst and vars = vars +
  base: grounding where
  subst = base_subst and vars = base_vars and is_ground = base_is_ground and 
  to_ground = base_to_ground and from_ground = base_from_ground
for
  vars :: "'expr  'var set" and
  base_subst :: "'base  'subst  'base" and
  base_to_ground :: "'base  'baseG" and
  base_from_ground +
fixes 
  entails_def :: "'expr  bool" ("( _)" [50] 50) and 
  I ::  "('baseG × 'baseG) set"
assumes
  congruence: "expr γ x update.
        base_is_ground update 
        base_is_ground (x ⋅v γ) 
        (base_to_ground (x ⋅v γ), base_to_ground update)  I 
        is_ground (expr  γ) 
         expr  γx := update 
         expr  γ"
begin

abbreviation entails where
  "entails  entails_def"

end

locale symmetric_entailment = entailment +
  assumes sym: "sym I"
begin

lemma symmetric_congruence:
  assumes
    update_is_ground: "base_is_ground update" and
    var_grounding: "base_is_ground (x ⋅v γ)" and
    var_update: "(base_to_ground (x ⋅v γ), base_to_ground update)  I" and
    expr_grounding: "is_ground (subst expr γ)"
  shows " expr  γx := update   expr  γ"
proof (rule iffI)
  assume " expr  γx := update"

  then show " expr  γ"
    by(rule congruence[OF assms])
next
  assume expr_γ: " expr  γ"

  show " expr  γx := update"
  proof (cases based.base.exists_nonground)
    case exists_nonground: True

    show ?thesis
    proof (rule congruence[OF var_grounding, of x "γx := update" expr])

      show "base_is_ground (x ⋅v γx := update)"
        by (metis update_is_ground based.exists_nonground_iff_base_exists_nonground
            based.subst_update_var(1))
    next

      show "(base_to_ground (x ⋅v γx := update), base_to_ground (x ⋅v γ))  I"
        by (metis based.exists_nonground_iff_base_exists_nonground based.subst_update_var(1)
            exists_nonground local.sym symE var_update)
    next

      show "is_ground (expr  γx := update)"
        by (simp add: expr_grounding update_is_ground)
    next

      show " expr  (γx := update)x := x ⋅v γ"
        by (simp add: expr_γ)
    qed
  next
    case False

    then show ?thesis
      using expr_γ based.exists_nonground_iff_base_exists_nonground
      by auto
  qed
qed

end

locale symmetric_base_entailment =
  base_substitution where subst = subst +
  based_subst_update where 
  subst = subst and base_subst = subst and base_is_ground = is_ground and base_vars = vars +

  grounding where subst = subst and to_ground = to_ground for
  subst :: "'base  'subst  'base"  (infixl "" 70) and
  to_ground :: "'base  'baseG" +
fixes I :: "('baseG × 'baseG) set"
assumes
  sym: "sym I" and
  congruence: "expr expr' update γ x.
      is_ground update 
      is_ground (x ⋅v γ) 
      (to_ground (x ⋅v γ), to_ground update)  I 
      is_ground (expr  γ) 
      (to_ground (expr  γx := update), expr')  I 
      (to_ground (expr  γ), expr')  I"
begin

lemma symmetric_congruence:
  assumes
    update_is_ground: "is_ground update" and
    var_grounding: "is_ground (x ⋅v γ)" and
    expr_grounding: "is_ground (expr  γ)" and
    var_update: "(to_ground (x ⋅v γ), to_ground update)  I"
  shows "(to_ground (expr  γx := update), expr')  I  (to_ground (expr  γ), expr')  I"
  using assms congruence[OF var_grounding, of x "γx := update"] congruence
  by (metis all_subst_ident_if_ground ground_subst_update sym subst_update(2) subst_update_twice
      subst_update_var(1) symE)

lemma simultaneous_congruence:
  assumes
    "is_ground update" and "is_ground update'"  and
    "is_ground (x ⋅v γ)" and "is_ground (x' ⋅v γ)"
    "(to_ground (x ⋅v γ), to_ground update)  I" and
    "(to_ground (x' ⋅v γ), to_ground update')  I" and
    "is_ground (expr  γ)" "is_ground (expr'  γ)"
  shows
    "(to_ground (expr  (γx := update)), to_ground (expr'  (γx' := update')))  I 
        (to_ground (expr  γ), to_ground (expr'  γ))  I"
  using assms
  by (meson sym symD symmetric_congruence)

lemma simultaneous_congruence_same:
  assumes
    "is_ground update" and "is_ground (x ⋅v γ)" and
    "(to_ground (x ⋅v γ), to_ground update)  I" and
     "is_ground (expr  γ)" "is_ground (expr'  γ)"
  shows
    "(to_ground (expr  (γx := update)), to_ground (expr'  (γx := update)))  I 
        (to_ground (expr  γ), to_ground (expr'  γ))  I"
  using simultaneous_congruence assms
  by metis

end

locale entailment_lifting =
  based_substitution_lifting where map = "map :: ('sub  'sub)  'expr  'expr" +
  finite_variables_lifting +
  based_subst_update_lifting +

  sub: symmetric_entailment where
  subst = sub_subst and vars = sub_vars and is_ground = sub_is_ground and entails_def = sub_entails
  for sub_entails ("(s _)" [50] 50) +
  fixes
    is_negated :: "'expr  bool" and
    empty :: bool and
    connective :: "bool  bool  bool" and
    entails_def ("( _)" [50] 50)
  assumes
    is_negated_subst: "expr σ. is_negated (expr  σ)  is_negated expr" and
    entails_def: "expr.  expr 
      (if is_negated expr then Not else (λx. x))
        (Finite_Set.fold connective empty (sub_entails  ` to_set expr))"
begin

sublocale symmetric_entailment where 
  subst = subst and vars = vars and is_ground = is_ground and entails_def = entails_def
proof unfold_locales
  fix expr γ x update P
  assume
    "base_is_ground update"
    "base_is_ground (x ⋅v γ)"
    "is_ground (expr  γ)"
    "(base_to_ground (x ⋅v γ), base_to_ground update)  I"
    " expr  γx := update"

  moreover then have "sub  to_set expr. (s sub s γx := update)  s sub s γ"
    using sub.symmetric_congruence to_set_is_ground_subst
    by blast

  ultimately show " expr  γ"
    unfolding is_negated_subst entails_def
    by(auto simp: image_image subst_def)
qed (rule sub.sym)

end

locale entailment_lifting_conj = entailment_lifting where
  connective = "(∧)" and empty = True

locale entailment_lifting_disj = entailment_lifting where
  connective = "(∨)" and empty = False

end