Theory Term_Rewrite_System

theory Term_Rewrite_System
  imports
    Regular_Tree_Relations.Ground_Ctxt
begin

definition compatible_with_gctxt :: "'f gterm rel  bool" where
  "compatible_with_gctxt I  (t t' ctxt. (t, t')  I  (ctxttG, ctxtt'G)  I)"

lemma compatible_with_gctxtD:
  "compatible_with_gctxt I  (t, t')  I  (ctxttG, ctxtt'G)  I"
  by (simp add: compatible_with_gctxt_def)

lemma compatible_with_gctxt_converse:
  assumes "compatible_with_gctxt I"
  shows "compatible_with_gctxt (I¯)"
  unfolding compatible_with_gctxt_def
proof (intro allI impI)
  fix t t' ctxt
  assume "(t, t')  I¯"
  thus "(ctxttG, ctxtt'G)  I¯"
    by (simp add: assms compatible_with_gctxtD)
qed

lemma compatible_with_gctxt_symcl:
  assumes "compatible_with_gctxt I"
  shows "compatible_with_gctxt (I)"
  unfolding compatible_with_gctxt_def
proof (intro allI impI)
  fix t t' ctxt
  assume "(t, t')  I"
  thus "(ctxttG, ctxtt'G)  I"
  proof (induction ctxt arbitrary: t t')
    case GHole
    thus ?case by simp
  next
    case (GMore f ts1 ctxt ts2)
    thus ?case
      using assms[unfolded compatible_with_gctxt_def, rule_format]
      by blast
  qed
qed

lemma compatible_with_gctxt_rtrancl:
  assumes "compatible_with_gctxt I"
  shows "compatible_with_gctxt (I*)"
  unfolding compatible_with_gctxt_def
proof (intro allI impI)
  fix t t' ctxt
  assume "(t, t')  I*"
  thus "(ctxttG, ctxtt'G)  I*"
  proof (induction t' rule: rtrancl_induct)
    case base
    show ?case
      by simp
  next
    case (step y z)
    thus ?case
      using assms[unfolded compatible_with_gctxt_def, rule_format]
      by (meson rtrancl.rtrancl_into_rtrancl)
  qed
qed

lemma compatible_with_gctxt_relcomp:
  assumes "compatible_with_gctxt I1" and "compatible_with_gctxt I2"
  shows "compatible_with_gctxt (I1 O I2)"
  unfolding compatible_with_gctxt_def
proof (intro allI impI)
  fix t t'' ctxt
  assume "(t, t'')  I1 O I2"
  then obtain t' where "(t, t')  I1" and "(t', t'')  I2"
    by auto

  have "(ctxttG, ctxtt'G)  I1"
    using (t, t')  I1 assms(1) compatible_with_gctxtD by blast
  moreover have "(ctxtt'G, ctxtt''G)  I2"
    using (t', t'')  I2 assms(2) compatible_with_gctxtD by blast
  ultimately show "(ctxttG, ctxtt''G)  I1 O I2"
    by auto
qed

lemma compatible_with_gctxt_join:
  assumes "compatible_with_gctxt I"
  shows "compatible_with_gctxt (I)"
  using assms
  by (simp_all add: join_def compatible_with_gctxt_relcomp compatible_with_gctxt_rtrancl
      compatible_with_gctxt_converse)

lemma compatible_with_gctxt_conversion:
  assumes "compatible_with_gctxt I"
  shows "compatible_with_gctxt (I*)"
  by (simp add: assms compatible_with_gctxt_rtrancl compatible_with_gctxt_symcl conversion_def)

definition rewrite_inside_gctxt :: "'f gterm rel  'f gterm rel" where
  "rewrite_inside_gctxt R = {(ctxtt1G, ctxtt2G) | ctxt t1 t2. (t1, t2)  R}"

lemma mem_rewrite_inside_gctxt_if_mem_rewrite_rules[intro]:
  "(l, r)  R  (l, r)  rewrite_inside_gctxt R"
  by (metis (mono_tags, lifting) CollectI gctxt_apply_term.simps(1) rewrite_inside_gctxt_def)

lemma ctxt_mem_rewrite_inside_gctxt_if_mem_rewrite_rules[intro]:
  "(l, r)  R  (ctxtlG, ctxtrG)  rewrite_inside_gctxt R"
  by (auto simp: rewrite_inside_gctxt_def)

lemma rewrite_inside_gctxt_mono: "R  S  rewrite_inside_gctxt R  rewrite_inside_gctxt S"
  by (auto simp add: rewrite_inside_gctxt_def)

lemma rewrite_inside_gctxt_union:
  "rewrite_inside_gctxt (R  S) = rewrite_inside_gctxt R  rewrite_inside_gctxt S"
  by (auto simp add: rewrite_inside_gctxt_def)

lemma rewrite_inside_gctxt_insert:
  "rewrite_inside_gctxt (insert r R) = rewrite_inside_gctxt {r}  rewrite_inside_gctxt R"
  using rewrite_inside_gctxt_union[of "{r}" R, simplified] .

lemma converse_rewrite_steps: "(rewrite_inside_gctxt R)¯ = rewrite_inside_gctxt (R¯)"
  by (auto simp: rewrite_inside_gctxt_def)

lemma rhs_lt_lhs_if_rule_in_rewrite_inside_gctxt:
  fixes less_trm :: "'f gterm  'f gterm  bool" (infix "t" 50)
  assumes
    rule_in: "(t1, t2)  rewrite_inside_gctxt R" and
    ball_R_rhs_lt_lhs: "t1 t2. (t1, t2)  R  t2 t t1" and
    compatible_with_gctxt: "t1 t2 ctxt. t2 t t1  ctxtt2G t ctxtt1G"
  shows "t2 t t1"
proof -
  from rule_in obtain t1' t2' ctxt where
    "(t1', t2')  R" and
    "t1 = ctxtt1'G" and
    "t2 = ctxtt2'G"
    by (auto simp: rewrite_inside_gctxt_def)

  from ball_R_rhs_lt_lhs have "t2' t t1'"
    using (t1', t2')  R by simp

  with compatible_with_gctxt have "ctxtt2'G t ctxtt1'G"
    by metis

  thus ?thesis
    using t1 = ctxtt1'G t2 = ctxtt2'G by metis
qed

lemma mem_rewrite_step_union_NF:
  assumes "(t, t')  rewrite_inside_gctxt (R1  R2)"
    "t  NF (rewrite_inside_gctxt R2)"
  shows "(t, t')  rewrite_inside_gctxt R1"
  using assms
  unfolding rewrite_inside_gctxt_union
  by blast

lemma predicate_holds_of_mem_rewrite_inside_gctxt:
  assumes rule_in: "(t1, t2)  rewrite_inside_gctxt R" and
    ball_P: "t1 t2. (t1, t2)  R  P t1 t2" and
    preservation: "t1 t2 ctxt σ. (t1, t2)  R  P t1 t2  P ctxtt1G ctxtt2G"
  shows "P t1 t2"
proof -
  from rule_in obtain t1' t2' ctxt σ where
    "(t1', t2')  R" and
    "t1 = ctxtt1'G" and
    "t2 = ctxtt2'G"
    by (auto simp: rewrite_inside_gctxt_def)
  thus ?thesis
    using ball_P[OF (t1', t2')  R]
    using preservation[OF (t1', t2')  R, of ctxt]
    by simp
qed

lemma compatible_with_gctxt_rewrite_inside_gctxt[simp]: "compatible_with_gctxt (rewrite_inside_gctxt E)"
  unfolding compatible_with_gctxt_def rewrite_inside_gctxt_def
  unfolding mem_Collect_eq
  by (metis Pair_inject ctxt_ctxt)

lemma subset_rewrite_inside_gctxt[simp]: "E  rewrite_inside_gctxt E"
proof (rule Set.subsetI)
  fix e assume e_in: "e  E"
  moreover obtain s t where e_def: "e = (s, t)"
    by fastforce
  show "e  rewrite_inside_gctxt E"
    unfolding rewrite_inside_gctxt_def
    unfolding mem_Collect_eq
  proof (intro exI conjI)
    show "e = (GsG, GtG)"
      unfolding e_def gctxt_apply_term.simps ..
  next
    show "(s, t)  E"
      using e_in
      unfolding e_def .
  qed
qed

lemma wf_converse_rewrite_inside_gctxt:
  fixes E :: "'f gterm rel"
  assumes
    wfP_R: "wfP R" and
    R_compatible_with_gctxt: "ctxt t t'. R t t'  R ctxttG ctxtt'G" and
    equations_subset_R: "x y. (x, y)  E  R y x"
  shows "wf ((rewrite_inside_gctxt E)¯)"
proof (rule wf_subset)
  from wfP_R show "wf {(x, y). R x y}"
    by (simp add: wfp_def)
next
  show "(rewrite_inside_gctxt E)¯  {(x, y). R x y}"
  proof (rule Set.subsetI)
    fix e assume "e  (rewrite_inside_gctxt E)¯"
    then obtain ctxt s t where e_def: "e = (ctxtsG, ctxttG)" and "(t, s)  E"
      by (smt (verit) Pair_inject converseE mem_Collect_eq rewrite_inside_gctxt_def)
    hence "R s t"
      using equations_subset_R by simp
    hence "R ctxtsG ctxttG"
      using R_compatible_with_gctxt by simp
    then show "e  {(x, y). R x y}"
      by (simp add: e_def)
  qed
qed

end