Theory Grounded_Selection_Function

theory Grounded_Selection_Function
  imports
    Nonground_Selection_Function
    Nonground_Typing
    HOL_Extra
begin

context nonground_typing
begin

abbreviation select_subst_stability_on_clause where
  "select_subst_stability_on_clause select selectG CG C 𝒱 γ 
    C  γ = clause.from_ground CG 
    selectG CG = clause.to_ground ((select C)  γ) 
    clause.is_welltyped_ground_instance C 𝒱 γ"

abbreviation select_subst_stability_on where
  "select_subst_stability_on select selectG N 
    CG   (clause.welltyped_ground_instances ` N). (C, 𝒱)  N. γ.
    select_subst_stability_on_clause select selectG CG C 𝒱 γ"

lemma obtain_subst_stable_on_select_grounding:
  fixes select :: "('f, 'v) select"
  obtains selectG where
    "select_subst_stability_on select selectG N"
    "is_select_grounding select selectG"
proof-
  let ?NG = "(clause.welltyped_ground_instances ` N)"

  {
    fix C 𝒱 γ
    assume
      "(C, 𝒱)  N"
      "clause.is_welltyped_ground_instance C 𝒱 γ"

    then have
      "γ'. (C', 𝒱')N. selectG.
        select_subst_stability_on_clause select selectG (clause.to_ground (C  γ)) C' 𝒱' γ'"
      by(intro exI[of _ γ], intro bexI[of _ "(C, 𝒱)"]) auto
  }

  then have
     "CG  ?NG. γ. (C, 𝒱)  N. selectG.
         select_subst_stability_on_clause select selectG CG C 𝒱 γ"
    unfolding clause.welltyped_ground_instances_def
    by auto

  then have selectG_exists_for_premises:
     "CG  ?NG. selectG γ. (C, 𝒱)  N.
         select_subst_stability_on_clause select selectG CG C 𝒱 γ"
    by blast

  obtain selectG_on_groundings where
    selectG_on_groundings: "select_subst_stability_on select selectG_on_groundings N"
    using Ball_Ex_comm(1)[OF selectG_exists_for_premises]
    unfolding prod.case_eq_if
    by fast

  define selectG where
    "CG. selectG CG = (
        if CG  ?NG
        then selectG_on_groundings CG
        else clause.to_ground (select (clause.from_ground CG))
    )"

  have grounding: "is_select_grounding select selectG"
    using selectG_on_groundings
    unfolding is_select_grounding_def selectG_def prod.case_eq_if
    by (metis (no_types, lifting) clause.from_ground_inverse clause.ground_is_ground
        clause.subst_id_subst)

  show ?thesis
    using that[OF _ grounding] selectG_on_groundings
    unfolding selectG_def
    by fastforce
qed

end

locale grounded_selection_function =
  nonground_selection_function select +
  nonground_typing 
  for
    select :: "('f, 'v :: infinite) atom clause  ('f, 'v) atom clause" and
     :: "('f, 'ty) fun_types" +
fixes selectG
assumes selectG: "is_select_grounding select selectG"
begin

abbreviation subst_stability_on where
  "subst_stability_on N  select_subst_stability_on select selectG N"

lemma selectG_subset: "selectG C ⊆# C"
  using selectG
  unfolding is_select_grounding_def
  by (metis select_subset clause.to_ground_def image_mset_subseteq_mono clause.subst_def)

lemma selectG_negative_literals:
  assumes "lG ∈# selectG CG"
  shows "is_neg lG"
proof -
  obtain C γ where
    is_ground: "clause.is_ground (C  γ)" and
    selectG: "selectG CG = clause.to_ground (select C  γ)"
    using selectG
    unfolding is_select_grounding_def
    by blast

  show ?thesis
    using
      ground_literal_in_selection[
        OF select_ground_subst[OF is_ground] assms[unfolded selectG],
        THEN select_neg_subst
        ]
    by simp

qed

sublocale ground: selection_function selectG
  by unfold_locales (simp_all add: selectG_subset selectG_negative_literals)

end

end