Theory Abstract_Substitution.Based_Substitution

theory Based_Substitution contributor ‹Balazs Toth› 
  imports Substitution
begin

section ‹Substitutions on base expressions›

locale base_substitution = substitution where vars = vars and apply_subst = apply_subst
  for vars :: "'base  'v set" and apply_subst :: "'v  'subst  'base" (infixl ⋅v 69) +
  assumes 
    vars_id_subst [simp]: "x. vars (x ⋅v id_subst) = {x}" and
    comp_subst_iff: "σ σ' x. x ⋅v σ  σ' = subst (x ⋅v σ) σ'" and
    base_vars_subst: "expr ρ. vars (expr  ρ) =  (vars ` var_subst ρ ` vars expr)"

locale based_substitution =
  substitution where vars = vars and apply_subst = "apply_subst :: 'v  'subst  'base" +
  base: base_substitution where subst = base_subst and vars = base_vars 
for
  base_subst :: "'base  'subst  'base" and
  base_vars :: "'base  'v set" and
  vars :: "'expr  'v set"  +
assumes
  ground_subst_iff_base_ground_subst [simp]: "γ. is_ground_subst γ  base.is_ground_subst γ" and
  vars_subst: "expr ρ. vars (expr  ρ) =  (base_vars ` var_subst ρ ` vars expr)"
begin

lemma id_subst_subst [simp]: "base_subst (x ⋅v id_subst) σ = x ⋅v σ"
  by (metis base.comp_subst_iff left_neutral)

lemma vars_id_subst_update: "vars (expr  id_substx := b)  vars expr  base_vars b"
  unfolding fun_upd_def vars_subst
  using subst_update
  by (smt (verit, del_insts) SUP_least UnCI base.vars_id_subst image_iff singletonD subsetI)

lemma is_grounding_iff_vars_grounded:
  "is_ground (expr  γ)  (x  vars expr. base.is_ground (x ⋅v γ))"
  using vars_subst
  by auto

lemma variable_grounding:
  assumes "is_ground (expr  γ)" "x  vars expr"
  shows "base.is_ground (x ⋅v γ)"
  using assms is_grounding_iff_vars_grounded
  by blast

definition range_vars :: "'subst  'v set" where
  "range_vars σ = (base_vars ` subst_range σ)"

lemma vars_subst_subset: "vars (expr  σ)  (vars expr - subst_domain σ)  range_vars σ"
  unfolding subst_domain_def range_vars_def vars_subst
  using base.vars_id_subst
  by (smt (verit, del_insts) Diff_iff UN_iff UnCI image_iff mem_Collect_eq singletonD subsetI)

lemma ground_subst_update [simp]:
  assumes "base.is_ground update" "is_ground (expr  γ)"
  shows "is_ground (expr  γx := update)"
  using assms is_grounding_iff_vars_grounded
  by (metis subst_update)

end

context base_substitution
begin

sublocale based_substitution
  where base_subst = subst and base_vars = vars
  by unfold_locales (simp_all add: base_vars_subst)

declare ground_subst_iff_base_ground_subst [simp del]

end

hide_fact base_substitution.base_vars_subst


section ‹Properties of substitutions on base expressions›

locale base_exists_ground_subst = 
  base_substitution where
    vars = "vars :: 'base  'v set" and apply_subst = "apply_subst  :: 'v  'subst  'base" +
  subst_updates + 
  assumes
    base_ground_exists: "expr. is_ground expr"
begin

lemma redundant_subst_updates [simp]:
  assumes "x. x  vars expr  update x = None"
  shows "expr  subst_updates σ update = expr  σ"
proof (rule subst_eq)
  fix x
  assume "x  vars expr"

  then have "update x = None"
    using assms
    by metis

  then show "x ⋅v subst_updates σ update = x ⋅v σ"
    by simp
qed

lemma redundant_subst_updates_vars_set [simp]:
  assumes "x. x  X  update x = None"
  shows "(λx. x ⋅v subst_updates σ update) ` X = (λx. x ⋅v σ) ` X"
  using assms subst_updates 
  by auto

lemma redundant_subst_updates_vars_image [simp]:
  assumes "x. x  (vars ` X)  update x = None"
  shows "(λexpr. expr  subst_updates σ update) ` X = (λexpr. expr  σ) ` X"
  using assms subst_updates 
  by (meson UN_I image_cong redundant_subst_updates)

sublocale exists_ground_subst
proof unfold_locales
   obtain b where is_ground: "is_ground b"
    using base_ground_exists 
    by blast

  define γ :: 'subst where
    "x. γ  subst_updates id_subst (λ_. Some b)"

  show "γ. is_ground_subst γ"
  proof (rule exI)
    show "is_ground_subst γ"
      unfolding is_ground_subst_def γ_def
      by (simp add: is_ground is_grounding_iff_vars_grounded)
  qed
qed

end

locale base_exists_non_ident_subst =
  base_substitution where vars = vars + 
  finite_variables where vars = vars +
  infinite_variables where vars = vars +
  all_subst_ident_iff_ground where vars = vars
  for vars :: "'expr  'v set" 
begin

sublocale exists_non_ident_subst
proof unfold_locales
  fix expr and S :: "'expr set"
  assume finite_S: "finite S" and vars_not_empty: "vars expr  {}"

  obtain x where x: "x  vars expr"
    using vars_not_empty
    by blast

  have "finite (vars_set S)"
    using finite_S finite_vars
    unfolding vars_set_def
    by blast

  obtain y where y: "y  vars expr" "y  vars_set S"
  proof -

    have "finite (vars_set S)"
      using finite_S finite_vars
      unfolding vars_set_def
      by blast

    then have "finite (vars expr  vars_set S)"
      using finite_vars
      by simp

    then show ?thesis
      using that infinite_vars finite_vars
      by (meson UnCI ex_new_if_finite)
  qed

  define σ where "σ  id_substx := y ⋅v id_subst"

  show "σ. expr  σ  expr  expr  σ  S"
  proof (intro exI conjI)

    have y_in_expr_σ: "y  vars (expr  σ)"
      unfolding σ_def
      using x vars_subst
      by fastforce

    then show "expr  σ  expr"
      using y
      by metis

    show "expr  σ  S"
      using y_in_expr_σ y(2)
      unfolding vars_set_def
      by auto
  qed
qed

end

locale variables_in_base_imgu = based_substitution +
  assumes variables_in_base_imgu:
    "expr μ XX.
        base.is_imgu μ XX  finite XX  X  XX. finite X 
        vars (expr  μ)  vars expr  ((base_vars `  XX))"

locale base_variables_in_base_imgu =
  base_substitution where vars = "vars :: 'expr  'v set" and
  subst_update = "subst_update :: 'subst  'v  'expr  'subst" + 
  finite_variables +
  infinite_variables +
assumes
  not_back_to_id_subst: "expr σ. x. expr  σ = x ⋅v id_subst  x. expr = x ⋅v id_subst"
begin

lemma imgu_subst_domain_subset:
  assumes imgu: "is_imgu μ XX" and finite_X: "XXX. finite X" and finite_XX: "finite XX"
  shows "subst_domain μ   (vars `  XX)"
proof (intro Set.subsetI)
  fix x
  assume "x  subst_domain μ"

  then have x_μ: "x ⋅v μ  x ⋅v id_subst"
    unfolding subst_domain_def
    by auto

  show "x   (vars `  XX)"
  proof (rule ccontr)
    assume x: "x   (vars `  XX)"

    define τ where 
      "τ  μx := x ⋅v id_subst"

    have "x ⋅v μ  τ  x ⋅v τ"
    proof (cases "y. x ⋅v μ = y ⋅v id_subst")
      case True

      then obtain y where y: "x ⋅v μ = y ⋅v id_subst"
        by auto

      then have "x  y"
        using x_μ
        by blast

      moreover have "y ⋅v μ  x ⋅v id_subst"
      proof (rule notI)
        assume "y ⋅v μ = x ⋅v id_subst"

        then show False
          using imgu x_μ
          unfolding is_imgu_def
          by (metis comp_subst_iff id_subst_subst)
      qed

      ultimately show ?thesis
        unfolding comp_subst_iff y τ_def
        by auto
    next
      case False

      then show ?thesis
        unfolding τ_def comp_subst_iff
        using not_back_to_id_subst
        by (metis subst_update(1))
    qed

    then have "μ  τ  τ"
      by metis

    moreover have "is_unifier_set τ XX"
      using imgu is_imgu_def
      unfolding τ_def is_unifier_set_def is_unifier_def subst_set_def
      using x
      by auto

    ultimately show False
      using imgu
      unfolding is_imgu_def
      by auto
  qed
qed

lemma imgu_subst_domain_finite:
  assumes imgu: "is_imgu μ XX" and finite_X: "XXX. finite X" and finite_XX: "finite XX"
  shows "finite (subst_domain μ)"
  using imgu_subst_domain_subset[OF assms(1-3)] finite_XX finite_X finite_vars
  by (simp add: finite_subset)

lemma imgu_range_vars_finite:
  assumes imgu: "is_imgu μ XX" and finite_X: "XXX. finite X" and finite_XX: "finite XX"
  shows "finite (range_vars μ)"
  using imgu_subst_domain_finite[OF assms] finite_vars
  unfolding range_vars_def
  by blast

lemma imgu_range_vars_vars_subset:
  assumes imgu: "is_imgu μ XX" and finite_X: "XXX. finite X" and finite_XX: "finite XX"
  shows "(vars ` expr_subst μ `  XX)   (vars `  XX)"
proof (intro Set.subsetI)
  fix y
  assume y: "y   (vars ` expr_subst μ `  XX)"

  then obtain x where
    x: "x  (vars `  XX)" "y  vars (x ⋅v μ)"
    using vars_subst
    by auto

  show "y   (vars `  XX)"
  proof (rule ccontr)
    assume y': "y   (vars `  XX)"

    then have x_neq_y: "x  y"
      using x
      by auto

    obtain z where z: "z  range_vars μ" "z  subst_domain μ"
      using 
        imgu_subst_domain_finite[OF assms]
        imgu_range_vars_finite[OF assms]
        infinite_vars
      by (metis Diff_iff finite_Diff2 infinite_super subsetI)

    define τ where
      "τ  id_substy := z ⋅v id_subst  μ"

    have "x ⋅v μ  τ  x ⋅v τ"
    proof -

      have "z  vars (x ⋅v μ)"
        using z(1) x(2) x_neq_y
        unfolding range_vars_def subst_domain_def
        by force

      moreover have "z  vars (x ⋅v μ  id_substy := z ⋅v id_subst)"
        using x(2) vars_subst
        by fastforce

      then have "z  vars (x ⋅v μ  id_substy := z ⋅v id_subst  μ)"
        using z(2) vars_subst
        unfolding range_vars_def subst_domain_def
        by fastforce

      ultimately show ?thesis
        using x_neq_y
        unfolding τ_def comp_subst_iff
        by auto
    qed

    then have "μ  τ  τ"
      by metis

    moreover have "is_unifier_set τ XX"
      using imgu is_imgu_def
      unfolding τ_def is_unifier_set_def is_unifier_def subst_set_def
      using y'
      by auto

    ultimately show False
      using imgu
      unfolding is_imgu_def
      by auto
  qed
qed

lemma range_vars_subset_if_is_imgu:
  assumes "is_imgu μ XX" "XXX. finite X" "finite XX"
  shows "range_vars μ  (exprXX. vars expr)"
proof -
  have "range_vars μ = (x  subst_domain μ. vars (x ⋅v μ))"
    by (simp add: range_vars_def)

  also have "  ((vars ` (λexpr. expr  μ) `  XX))"
    using imgu_subst_domain_subset[OF assms] subsetD vars_subst 
    by fastforce

  also have "  (exprXX. vars expr)"
    using imgu_range_vars_vars_subset[OF assms] .

  finally show ?thesis .
qed

sublocale variables_in_base_imgu where 
  base_subst = subst and base_vars = vars
  using range_vars_subset_if_is_imgu vars_subst_subset
  by unfold_locales fastforce

end

locale range_vars_subset_if_is_imgu = base_substitution +
  assumes range_vars_subset_if_is_imgu: 
    "μ XX. is_imgu μ XX  XXX. finite X  finite XX 
        range_vars μ  (exprXX. vars expr)"
begin

sublocale variables_in_base_imgu where 
  base_subst = subst and base_vars = vars
  using range_vars_subset_if_is_imgu vars_subst_subset
  by unfold_locales fastforce

end

end