Theory First_Order_Clause.Grounded_Selection_Function

theory Grounded_Selection_Function
  imports
    Nonground_Selection_Function
    HOL_Extra
begin

context groundable_nonground_clause
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)  γ) 
    is_ground_instance Γ C γ"

abbreviation uncurried_ground_instances where
  "uncurried_ground_instances C  ground_instances (fst C) (snd C)"

abbreviation select_subst_stability_on where
  "select_subst_stability_on select selectG N 
    CG   (uncurried_ground_instances ` N). (e, C)  N. γ.
      select_subst_stability_on_clause select selectG CG e C γ"

lemma obtain_subst_stable_on_select_grounding:
  fixes select :: "'a select"
  obtains selectG where
    "select_subst_stability_on select selectG N"
    "is_select_grounding select selectG"
proof -
  let ?NG = "(uncurried_ground_instances ` N)"

  {
    fix Γ C γ
    assume
      "(Γ, C)  N"
      "is_ground_instance Γ C γ"

    then have
      "γ'. (Γ', C')N. selectG.
         select_subst_stability_on_clause select selectG (clause.to_ground (C  γ)) Γ' C' γ'"
      using is_ground_instance_is_ground
      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 ground_instances_def
    by force

  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 (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 where select = select and atom_subst = atom_subst +
  groundable_nonground_clause where atom_subst = atom_subst
  for               
    select :: "'a select" and
    atom_subst :: "'a  ('v  't)  'a" +
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