Theory Inlining1Prod
section ‹Inlining a Single Production›
theory Inlining1Prod
imports Context_Free_Grammar
begin
text
‹A single production of ‹(A,α)› can be removed from ‹ps› by inlining
(= replacing ‹Nt A› by ‹α› everywhere in ‹ps›) without changing the language
if ‹Nt A ∉ set α› and ‹A ∉ lhss ps›.›
text
‹‹substP ps s u› replaces every occurrence of the symbol ‹s› with the list of symbols ‹u› on the right-hand sides of the production list ‹ps››
definition substP :: "('n, 't) sym ⇒ ('n, 't) syms ⇒ ('n, 't) prods ⇒ ('n, 't) prods" where
"substP s u ps = map (λ(A,v). (A, substs s u v)) ps"
lemma substP_split: "substP s u (ps @ ps') = substP s u ps @ substP s u ps'"
by (simp add: substP_def)
lemma substP_skip1: "s ∉ set v ⟹ substP s u ((A,v) # ps) = (A,v) # substP s u ps"
by (auto simp add: substs_skip substP_def)
lemma substP_skip2: "s ∉ syms ps ⟹ substP s u ps = ps"
by (induction ps) (auto simp add: substP_def substs_skip)
lemma substP_rev: "Nt B ∉ syms ps ⟹ substP (Nt B) [s] (substP s [Nt B] ps) = ps"
proof (induction ps)
case Nil
then show ?case
by (simp add: substP_def)
next
case (Cons a ps)
let ?A = "fst a" let ?u = "snd a" let ?substs = "substs s [Nt B]"
have "substP (Nt B) [s] (substP s [Nt B] (a # ps)) = substP (Nt B) [s] (map (λ(A,v). (A, ?substs v)) (a#ps))"
by (simp add: substP_def)
also have "... = substP (Nt B) [s] ((?A, ?substs ?u) # map (λ(A,v). (A, ?substs v)) ps)"
by (simp add: case_prod_unfold)
also have "... = map ((λ(A,v). (A, substsNt B [s] v))) ((?A, ?substs ?u) # map (λ(A,v). (A, ?substs v)) ps)"
by (simp add: substP_def)
also have "... = (?A, substsNt B [s] (?substs ?u)) # substP (Nt B) [s] (substP s [Nt B] ps)"
by (simp add: substP_def)
also from Cons have "... = (?A, substsNt B [s] (?substs ?u)) # ps"
using set_subset_Cons unfolding Syms_def by auto
also from Cons.prems have "... = (?A, ?u) # ps"
using substs_rev unfolding Syms_def by force
also have "... = a # ps" by simp
finally show ?case .
qed
lemma substP_der:
"(A,u) ∈ set (substP (Nt B) v ps) ⟹ set ((B,v) # ps) ⊢ [Nt A] ⇒* u"
proof -
assume "(A,u) ∈ set (substP (Nt B) v ps)"
then have "∃u'. (A,u') ∈ set ps ∧ u = substsNt B v u'" unfolding substP_def by auto
then obtain u' where u'_def: "(A,u') ∈ set ps ∧ u = substsNt B v u'" by blast
then have path1: "set ((B,v) # ps) ⊢ [Nt A] ⇒* u'"
by (simp add: derive_singleton r_into_rtranclp)
have "set ((B,v) # ps) ⊢ u' ⇒* substsNt B v u'"
using substs_der by (metis list.set_intros(1))
with u'_def have path2: "set ((B,v) # ps) ⊢ u' ⇒* u" by simp
from path1 path2 show ?thesis by simp
qed
text‹A list of symbols ‹u› can be derived before inlining if ‹u› can be derived after inlining.›
lemma if_part:
"set (substP (Nt B) v ps) ⊢ [Nt A] ⇒* u ⟹ set ((B,v) # ps) ⊢ [Nt A] ⇒* u"
proof (induction rule: derives_induct)
case (step u A v w)
then show ?case
by (meson derives_append derives_prepend rtranclp_trans substP_der)
qed simp
text
‹For the other implication we need to take care that ‹B› can be derived in the original ‹ps›.
Thus, after inlining, ‹B› must also be substituted in the derived sentence ‹u›:›
lemma only_if_lemma:
assumes "A ≠ B"
and "B ∉ lhss ps"
and "Nt B ∉ set v"
shows "set ((B,v)#ps) ⊢ [Nt A] ⇒* u ⟹ set (substP (Nt B) v ps) ⊢ [Nt A] ⇒* substsNt B v u"
proof (induction rule: derives_induct)
case base
then show ?case using assms(1) by simp
next
case (step s B' w v')
then show ?case
proof (cases "B = B'")
case True
then have "v = v'"
using ‹B ∉ lhss ps› step.hyps unfolding Lhss_def by auto
then have "substsNt B v (s @ [Nt B'] @ w) = substsNt B v (s @ v' @ w)"
using step.prems ‹Nt B ∉ set v› True by (simp add: substs_skip)
then show ?thesis
using step.IH by argo
next
case False
then have "(B',v') ∈ set ps"
using step by auto
then have "(B', substsNt B v v') ∈ set (substP (Nt B) v ps)"
by (metis (no_types, lifting) list.set_map pair_imageI substP_def)
from derives_rule[OF this _ rtranclp.rtrancl_refl] step.IH False show ?thesis
by simp
qed
qed
text
‹With the assumption that the non-terminal ‹B› is not in the list of symbols ‹u›, ‹substs u (Nt B) v› reduces to ‹u››
corollary only_if_part:
assumes "A ≠ B"
and "B ∉ lhss ps"
and "Nt B ∉ set v"
and "Nt B ∉ set u"
shows "set ((B,v)#ps) ⊢ [Nt A] ⇒* u ⟹ set (substP (Nt B) v ps) ⊢ [Nt A] ⇒* u"
by (metis assms substs_skip only_if_lemma)
text
‹Combining the two implications gives us the desired property of language preservation›
lemma derives_inlining:
assumes "B ∉ lhss ps" and
"Nt B ∉ set v" and
"Nt B ∉ set u" and
"A ≠ B"
shows "set (substP (Nt B) v ps) ⊢ [Nt A] ⇒* u ⟷ set ((B,v) # ps) ⊢ [Nt A] ⇒* u"
using assms if_part only_if_part by metis
end