Theory First_Order_Terms.Subterm_and_Context
section ‹Subterms and Contexts›
text ‹
  We define the (proper) sub- and superterm relations on first order terms,
  as well as contexts (you can think of contexts as terms with exactly one hole,
  where we can plug-in another term).
  Moreover, we establish several connections between these concepts as well as
  to other concepts such as substitutions.
›
theory Subterm_and_Context
  imports
    Term
    "Abstract-Rewriting.Abstract_Rewriting"
begin
subsection ‹Subterms›
text ‹The ∗‹superterm› relation.›
inductive_set
  supteq :: "(('f, 'v) term × ('f, 'v) term) set"
  where
    refl [simp, intro]: "(t, t) ∈ supteq" |
    subt [intro]: "u ∈ set ss ⟹ (u, t) ∈ supteq ⟹ (Fun f ss, t) ∈ supteq"
text ‹The ∗‹proper superterm› relation.›
inductive_set
  supt :: "(('f, 'v) term × ('f, 'v) term) set"
  where
    arg [simp, intro]: "s ∈ set ss ⟹ (Fun f ss, s) ∈ supt" |
    subt [intro]: "s ∈ set ss ⟹ (s, t) ∈ supt ⟹ (Fun f ss, t) ∈ supt"
hide_const suptp supteqp
hide_fact
  suptp.arg suptp.cases suptp.induct suptp.intros suptp.subt suptp_supt_eq
hide_fact
  supteqp.cases supteqp.induct supteqp.intros supteqp.refl supteqp.subt supteqp_supteq_eq
hide_fact (open) supt.arg supt.subt supteq.refl supteq.subt
subsubsection ‹Syntactic Sugar›
text ‹Infix syntax.›
abbreviation "supt_pred s t ≡ (s, t) ∈ supt"
abbreviation "supteq_pred s t ≡ (s, t) ∈ supteq"
abbreviation (input) "subt_pred s t ≡ supt_pred t s"
abbreviation (input) "subteq_pred s t ≡ supteq_pred t s"
notation
  supt (‹{⊳}›) and
  supt_pred (‹(_/ ⊳ _)› [56, 56] 55) and
  subt_pred (infix ‹⊲› 55) and
  supteq (‹{⊵}›) and
  supteq_pred (‹(_/ ⊵ _)› [56, 56] 55) and
  subteq_pred (infix ‹⊴› 55)
abbreviation subt (‹{⊲}›) where "{⊲} ≡ {⊳}¯"
abbreviation subteq (‹{⊴}›) where "{⊴} ≡ {⊵}¯"
text ‹Quantifier syntax.›
syntax
  "_All_supteq" :: "[idt, 'a, bool] ⇒ bool" (‹(3∀_⊵_./ _)› [0, 0, 10] 10)
  "_Ex_supteq" :: "[idt, 'a, bool] ⇒ bool" (‹(3∃_⊵_./ _)› [0, 0, 10] 10)
  "_All_supt" :: "[idt, 'a, bool] ⇒ bool" (‹(3∀_⊳_./ _)› [0, 0, 10] 10)
  "_Ex_supt" :: "[idt, 'a, bool] ⇒ bool" (‹(3∃_⊳_./ _)› [0, 0, 10] 10)
"_All_subteq" :: "[idt, 'a, bool] ⇒ bool" (‹(3∀_⊴_./ _)› [0, 0, 10] 10)
"_Ex_subteq" :: "[idt, 'a, bool] ⇒ bool" (‹(3∃_⊴_./ _)› [0, 0, 10] 10)
"_All_subt" :: "[idt, 'a, bool] ⇒ bool" (‹(3∀_⊲_./ _)› [0, 0, 10] 10)
"_Ex_subt" :: "[idt, 'a, bool] ⇒ bool" (‹(3∃_⊲_./ _)› [0, 0, 10] 10)
syntax_consts
  "_All_supteq" "_All_supt" "_All_subteq" "_All_subt" ⇌ All and
  "_Ex_supteq" "_Ex_supt" "_Ex_subteq" "_Ex_subt" ⇌ Ex
translations
  "∀x⊵y. P" ⇀ "∀x. x ⊵ y ⟶ P"
  "∃x⊵y. P" ⇀ "∃x. x ⊵ y ∧ P"
  "∀x⊳y. P" ⇀ "∀x. x ⊳ y ⟶ P"
  "∃x⊳y. P" ⇀ "∃x. x ⊳ y ∧ P"
"∀x⊴y. P" ⇀ "∀x. x ⊴ y ⟶ P"
"∃x⊴y. P" ⇀ "∃x. x ⊴ y ∧ P"
"∀x⊲y. P" ⇀ "∀x. x ⊲ y ⟶ P"
"∃x⊲y. P" ⇀ "∃x. x ⊲ y ∧ P"
print_translation ‹
let
  val All_binder = Mixfix.binder_name @{const_syntax All};
  val Ex_binder = Mixfix.binder_name @{const_syntax Ex};
  val impl = @{const_syntax "implies"};
  val conj = @{const_syntax "conj"};
  val supt = @{const_syntax "supt_pred"};
  val supteq = @{const_syntax "supteq_pred"};
  val trans =
   [((All_binder, impl, supt), ("_All_supt", "_All_subt")),
    ((All_binder, impl, supteq), ("_All_supteq", "_All_subteq")),
    ((Ex_binder, conj, supt), ("_Ex_supt", "_Ex_subt")),
    ((Ex_binder, conj, supteq), ("_Ex_supteq", "_Ex_subteq"))];
  fun matches_bound v t =
     case t of (Const ("_bound", _) $ Free (v', _)) => (v = v')
              | _ => false
  fun contains_var v = Term.exists_subterm (fn Free (x, _) => x = v | _ => false)
  fun mk x c n P = Syntax.const c $ Syntax_Trans.mark_bound_body x $ n $ P
  fun tr' q = (q,
    K (fn [Const ("_bound", _) $ Free (v, T), Const (c, _) $ (Const (d, _) $ t $ u) $ P] =>
      (case AList.lookup (=) trans (q, c, d) of
        NONE => raise Match
      | SOME (l, g) =>
          if matches_bound v t andalso not (contains_var v u) then mk (v, T) l u P
          else if matches_bound v u andalso not (contains_var v t) then mk (v, T) g t P
          else raise Match)
     | _ => raise Match));
in [tr' All_binder, tr' Ex_binder] end
›
subsubsection ‹Transitivity Reasoning for Subterms›
lemma supt_trans [trans]:
  "s ⊳ t ⟹ t ⊳ u ⟹ s ⊳ u"
  by (induct s t rule: supt.induct) auto
lemma trans_supt: "trans {⊳}" by (auto simp: trans_def dest: supt_trans)
lemma supteq_trans [trans]:
  "s ⊵ t ⟹ t ⊵ u ⟹ s ⊵ u"
  by (induct s t rule: supteq.induct) (auto)
text ‹Auxiliary lemmas about term size.›
lemma size_simp5:
  "s ∈ set ss ⟹ s ⊳ t ⟹ size t < size s ⟹ size t < Suc (size_list size ss)"
  by (induct ss) auto
lemma size_simp6:
  "s ∈ set ss ⟹ s ⊵ t ⟹ size t ≤ size s ⟹ size t ≤ Suc (size_list size ss)"
  by (induct ss) auto
lemma size_simp1:
  "t ∈ set ts ⟹ size t < Suc (size_list size ts)"
  by (induct ts) auto
lemma size_simp2:
  "t ∈ set ts ⟹ size t < Suc (Suc (size s + size_list size ts))"
  by (induct ts) auto
lemma size_simp3:
  assumes "(x, y) ∈ set (zip xs ys)"
  shows "size x < Suc (size_list size xs)"
  using set_zip_leftD [OF assms]  size_simp1 by auto
lemma size_simp4:
  assumes "(x, y) ∈ set (zip xs ys)"
  shows "size y < Suc (size_list size ys)"
  using set_zip_rightD [OF assms] using size_simp1 by auto
lemmas size_simps =
  size_simp1 size_simp2 size_simp3 size_simp4 size_simp5 size_simp6
declare size_simps [termination_simp]
lemma supt_size:
  "s ⊳ t ⟹ size s > size t"
  by (induct rule: supt.induct) (auto simp: size_simps)
lemma supteq_size:
  "s ⊵ t ⟹ size s ≥ size t"
  by (induct rule: supteq.induct) (auto simp: size_simps)
text ‹Reflexivity and Asymmetry.›
lemma reflcl_supteq [simp]:
  "supteq⇧= = supteq" by auto
lemma trancl_supteq [simp]:
  "supteq⇧+ = supteq"
  by (rule trancl_id) (auto simp: trans_def intro: supteq_trans)
lemma rtrancl_supteq [simp]:
  "supteq⇧* = supteq"
  unfolding trancl_reflcl[symmetric] by auto
lemma eq_supteq: "s = t ⟹ s ⊵ t" by auto
lemma supt_neqD: "s ⊳ t ⟹ s ≠ t" using supt_size by auto
lemma supteq_Var [simp]:
  "x ∈ vars_term t ⟹ t ⊵ Var x"
proof (induct t)
  case (Var y) then show ?case by (cases "x = y") auto
next
  case (Fun f ss) then show ?case by (auto)
qed
lemmas vars_term_supteq = supteq_Var
lemma term_not_arg [iff]:
  "Fun f ss ∉ set ss" (is "?t ∉ set ss")
proof
  assume "?t ∈ set ss"
  then have "?t ⊳ ?t" by (auto)
  then have "?t ≠ ?t" by (auto dest: supt_neqD)
  then show False by simp
qed
lemma supt_Fun [simp]:
  assumes "s ⊳ Fun f ss" (is "s ⊳ ?t") and "s ∈ set ss"
  shows "False"
proof -
  from ‹s ∈ set ss› have "?t ⊳ s" by (auto)
  then have "size ?t > size s" by (rule supt_size)
  from ‹s ⊳ ?t› have "size s > size ?t" by (rule supt_size)
  with ‹size ?t > size s› show False by simp
qed
lemma supt_supteq_conv: "s ⊳ t = (s ⊵ t ∧ s ≠ t)"
proof
  assume "s ⊳ t" then show "s ⊵ t ∧ s ≠ t"
  proof (induct rule: supt.induct)
    case (subt s ss t f)
    have "s ⊵ s" ..
    from ‹s ∈ set ss› have "Fun f ss ⊵ s" by (auto)
    from ‹s ⊵ t ∧ s ≠ t› have "s ⊵ t" ..
    with ‹Fun f ss ⊵ s› have first: "Fun f ss ⊵ t" by (rule supteq_trans)
    from ‹s ∈ set ss› and ‹s ⊳ t› have "Fun f ss ⊳ t" ..
    then have second: "Fun f ss ≠ t" by (auto dest: supt_neqD)
    from first and second show "Fun f ss ⊵ t ∧ Fun f ss ≠ t" by auto
  qed (auto simp: size_simps)
next
  assume "s ⊵ t ∧ s ≠ t"
  then have "s ⊵ t" and "s ≠ t" by auto
  then show "s ⊳ t" by (induct) (auto)
qed
lemma supt_not_sym: "s ⊳ t ⟹ ¬ (t ⊳ s)"
proof
  assume "s ⊳ t" and "t ⊳ s" then have "s ⊳ s" by (rule supt_trans)
  then show False unfolding supt_supteq_conv by simp
qed
lemma supt_irrefl[iff]: "¬ t ⊳ t"
  using supt_not_sym[of t t] by auto
lemma irrefl_subt: "irrefl {⊲}" by (auto simp: irrefl_def)
lemma supt_imp_supteq: "s ⊳ t ⟹ s ⊵ t"
  unfolding supt_supteq_conv by auto
lemma supt_supteq_not_supteq: "s ⊳ t = (s ⊵ t ∧ ¬ (t ⊵ s))"
  using supt_not_sym unfolding supt_supteq_conv by auto
lemma supteq_supt_conv: "(s ⊵ t) = (s ⊳ t ∨ s = t)" by (auto simp: supt_supteq_conv)
lemma supteq_antisym:
  assumes "s ⊵ t" and "t ⊵ s" shows "s = t"
  using assms unfolding supteq_supt_conv by (auto simp: supt_not_sym)
text ‹The subterm relation is an order on terms.›