Theory Disjoint_Union_CFG
section ‹Disjoint Union of Sets of Productions›
theory Disjoint_Union_CFG
imports
"Regular-Sets.Regular_Set"
Context_Free_Grammar
begin
text ‹This theory provides lemmas relevant when combining the productions of two grammars
with disjoint sets of nonterminals. In particular that the languages of the nonterminals of
one grammar is unchanged by adding productions involving only disjoint nonterminals.›
lemma derivel_disj_Un_if:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "P ∪ P' ⊢ u ⇒l v"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ⊢ u ⇒l v ∧ nts_syms v ∩ Lhss P' = {}"
proof -
from assms(2) obtain A w u' v' where
A_w: "(A, w)∈(P ∪ P')"
and u: "u = map Tm u' @ Nt A # v'"
and v: "v = map Tm u' @ w @ v'"
unfolding derivel_iff by fast
then have "(A,w) ∉ P'" using assms(3) unfolding nts_syms_def Lhss_def by auto
then have "(A,w) ∈ P" using A_w by blast
with u v have "(A, w) ∈ P"
and u: "u = map Tm u' @ Nt A # v'"
and v: "v = map Tm u' @ w @ v'" by auto
then have "P ⊢ u ⇒l v" using derivel.intros by fastforce
moreover have "nts_syms v ∩ Lhss P' = {}"
using u v assms ‹(A, w) ∈ P› unfolding nts_syms_def Nts_def Rhs_Nts_def by auto
ultimately show ?thesis by fast
qed
lemma derive_disj_Un_if:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "P ∪ P' ⊢ u ⇒ v"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ⊢ u ⇒ v ∧ nts_syms v ∩ Lhss P' = {}"
proof -
from assms(2) obtain A w u' v' where
A_w: "(A, w) ∈ P ∪ P'"
and u: "u = u' @ Nt A # v'"
and v: "v = u' @ w @ v'"
unfolding derive_iff by fast
then have "(A,w) ∉ P'" using assms(3) unfolding nts_syms_def Lhss_def by auto
then have "(A,w) ∈ P" using A_w by blast
with u v have "(A, w) ∈ P" and u: "u = u' @ Nt A # v'" and v: "v = u' @ w @ v'" by auto
then have "P ⊢ u ⇒ v" using derive.intros by fastforce
moreover have "nts_syms v ∩ Lhss P' = {}"
using u v assms ‹(A, w) ∈ P› unfolding nts_syms_def Nts_def Rhs_Nts_def by auto
ultimately show ?thesis by blast
qed
lemma deriveln_disj_Un_if:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
shows "⟦ P ∪ P' ⊢ u ⇒l(n) v; nts_syms u ∩ Lhss P' = {} ⟧ ⟹
P ⊢ u ⇒l(n) v ∧ nts_syms v ∩ Lhss P' = {}"
proof (induction n arbitrary: v)
case 0
then show ?case by simp
next
case (Suc n')
then obtain v' where split: "P ∪ P' ⊢ u ⇒l(n') v' ∧ P ∪ P' ⊢ v' ⇒l v"
by (meson relpowp_Suc_E)
with Suc have "P ⊢ u ⇒l(n') v' ∧ nts_syms v' ∩ Lhss P' = {}"
by fast
with Suc show ?case using assms derivel_disj_Un_if
by (metis split relpowp_Suc_I)
qed
lemma deriven_disj_Un_if:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
shows "⟦ P ∪ P' ⊢ u ⇒(n) v; nts_syms u ∩ Lhss P' = {} ⟧ ⟹
P ⊢ u ⇒(n) v ∧ nts_syms v ∩ Lhss P' = {}"
proof (induction n arbitrary: v)
case 0
then show ?case by simp
next
case (Suc n')
then obtain v' where split: "P ∪ P' ⊢ u ⇒(n') v' ∧ P ∪ P' ⊢ v' ⇒ v"
by (meson relpowp_Suc_E)
with Suc have "P ⊢ u ⇒(n') v' ∧ nts_syms v' ∩ Lhss P' = {}"
by fast
with Suc show ?case using assms derive_disj_Un_if
by (metis split relpowp_Suc_I)
qed
lemma derivel_disj_Un_iff:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ∪ P' ⊢ u ⇒l v ⟷ P ⊢ u ⇒l v"
using assms Un_derivel derivel_disj_Un_if by fastforce
lemma derive_disj_Un_iff:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ∪ P' ⊢ u ⇒ v ⟷ P ⊢ u ⇒ v"
using assms Un_derive derive_disj_Un_if by fastforce
lemma deriveln_disj_Un_iff:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ∪ P' ⊢ u ⇒l(n) v ⟷ P ⊢ u ⇒l(n) v"
by (metis Un_derivel assms(1,2) deriveln_disj_Un_if relpowp_mono)
lemma deriven_disj_Un_iff:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ∪ P' ⊢ u ⇒(n) v ⟷ P ⊢ u ⇒(n) v"
by (metis Un_derive assms(1,2) deriven_disj_Un_if relpowp_mono)
lemma derives_disj_Un_iff:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "nts_syms u ∩ Lhss P' = {}"
shows "P ∪ P' ⊢ u ⇒* v ⟷ P ⊢ u ⇒* v"
by (simp add: deriven_disj_Un_iff[OF assms] rtranclp_power)
lemma Lang_disj_Un1:
assumes "Rhs_Nts P ∩ Lhss P' = {}"
and "S ∉ Lhss P'"
shows "Lang P S = Lang (P ∪ P') S"
proof -
from assms(2) have "nts_syms [Nt S] ∩ Lhss P' = {}" unfolding nts_syms_def Lhss_def by simp
then show ?thesis unfolding Lang_def
by (simp add: derives_disj_Un_iff[OF assms(1)])
qed
subsection ‹Disjoint Concatenation›
lemma Lang_concat_disj:
assumes "Nts P1 ∩ Nts P2 = {}" "S ∉ Nts P1 ∪ Nts P2 ∪ {S1,S2}" "S1 ∉ Nts P2" "S2 ∉ Nts P1"
shows "Lang ({(S, [Nt S1,Nt S2])} ∪ (P1 ∪ P2)) S = Lang P1 S1 @@ Lang P2 S2"
proof -
let ?P = "{(S, [Nt S1,Nt S2])} ∪ (P1 ∪ P2)"
let ?L1 = "Lang P1 S1"
let ?L2 = "Lang P2 S2"
have "Lang ?P S ⊆ ?L1 @@ ?L2"
proof
fix w
assume "w ∈ Lang ?P S"
then have "?P ⊢ [Nt S] ⇒* map Tm w" using Lang_def by fastforce
then obtain α where "?P ⊢ α ⇒* map Tm w ∧ (S, α) ∈ ?P" using derives_start1 by fast
then have dervs: "?P ⊢ [Nt S1, Nt S2] ⇒* map Tm w" using assms unfolding Nts_def by auto
then obtain w1 w2 where "?P ⊢ [Nt S1] ⇒* map Tm w1" "?P ⊢ [Nt S2] ⇒* map Tm w2" "w = w1 @ w2"
using derives_append_decomp[of ?P "[Nt S1]" "[Nt S2]"] by (auto simp: map_eq_append_conv)
then have "P1 ∪ ({(S, [Nt S1,Nt S2])} ∪ P2) ⊢ [Nt S1] ⇒* map Tm w1"
and "P2 ∪ ({(S, [Nt S1,Nt S2])} ∪ P1) ⊢ [Nt S2] ⇒* map Tm w2" by (simp_all add: Un_commute)
from derives_disj_Un_iff[THEN iffD1, OF _ _ this(1)]
derives_disj_Un_iff[THEN iffD1, OF _ _ this(2)] assms
have "P1 ⊢ [Nt S1] ⇒* map Tm w1" "P2 ⊢ [Nt S2] ⇒* map Tm w2"
by (auto simp: Nts_Lhss_Rhs_Nts)
then have "w1 ∈ ?L1" "w2 ∈ ?L2" unfolding Lang_def by simp_all
with ‹w = _› show "w ∈ ?L1 @@ ?L2" by blast
qed
moreover
have "?L1 @@ ?L2 ⊆ Lang ?P S"
proof
fix w
assume "w ∈ ?L1 @@ ?L2"
then obtain w1 w2 where w12_src: "w1 ∈ ?L1 ∧ w2 ∈ ?L2 ∧ w = w1 @ w2" using assms by blast
have "P1 ⊆ ?P" "P2 ⊆ ?P" by auto
from w12_src have 1: "P1 ⊢ [Nt S1] ⇒* map Tm w1" and 2: "P2 ⊢ [Nt S2] ⇒* map Tm w2"
using Lang_def by fast+
have "?P ⊢ [Nt S] ⇒ [Nt S1, Nt S2]"
using derive.intros[of "S" "[Nt S1, Nt S2]" ?P "[]"] by auto
also have "?P ⊢ ... ⇒* map Tm w1 @ [Nt S2]" using derives_append derives_mono[OF ‹P1 ⊆ ?P›]
using derives_append[OF derives_mono[OF ‹P1 ⊆ ?P› 1], of "[Nt S2]"] by simp
also have "?P ⊢ … ⇒* map Tm w1 @ map Tm w2"
using derives_prepend[OF derives_mono[OF ‹P2 ⊆ ?P› 2]] by simp
ultimately have "?P ⊢ [Nt S] ⇒* map Tm w" using w12_src by simp
then show "w ∈ Lang ?P S" unfolding Lang_def by auto
qed
ultimately show ?thesis by blast
qed
subsection ‹Disjoint Union including start fork›
lemma derive_from_isolated_fork:
"⟦ A ∉ Lhss P; {(A,α1),(A,α2)} ∪ P ⊢ [Nt A] ⇒ β ⟧ ⟹ β = α1 ∨ β = α2"
unfolding derive_singleton by(auto simp: Lhss_def)
lemma derives_fork_if_derives1:
assumes "P ⊢ [Nt B1] ⇒* map Tm w"
shows "{(A,[Nt B1]), (A,[Nt B2])} ∪ P ⊢ [Nt A] ⇒* map Tm w" (is "?P ⊢ _ ⇒* _")
proof -
have "?P ⊢ [Nt A] ⇒ [Nt B1]" using derive_singleton by auto
also have "?P ⊢ [Nt B1] ⇒* map Tm w" using assms
by (meson derives_mono sup_ge2)
finally show ?thesis .
qed
lemma derives_disj_if_derives_fork:
assumes "A ∉ Nts P ∪ {B1,B2}"
and "{(A,[Nt B1]), (A,[Nt B2])} ∪ P ⊢ [Nt A] ⇒* map Tm w" (is "?P ⊢ _ ⇒* _")
shows "P ⊢ [Nt B1] ⇒* map Tm w ∨ P ⊢ [Nt B2] ⇒* map Tm w"
proof -
obtain β where steps: "?P ⊢ [Nt A] ⇒ β" "?P ⊢ β ⇒* map Tm w"
using converse_rtranclpE[OF assms(2)] by blast
have "β = [Nt B1] ∨ β = [Nt B2]"
using steps(1) derive_from_isolated_fork[of A P] assms(1) by(auto simp: Nts_Lhss_Rhs_Nts)
then show ?thesis
using steps(2) derives_disj_Un_iff[of P "{(A,[Nt B1]), (A,[Nt B2])}" β] assms
by(auto simp: Nts_Lhss_Rhs_Nts)
qed
lemma Lang_distrib_eq_Un_Lang2:
assumes "A ∉ Nts P ∪ {B1,B2}"
shows "Lang ({(A,[Nt B1]),(A,[Nt B2])} ∪ P) A = (Lang P B1 ∪ Lang P B2)"
(is "Lang ?P _ = _" is "?L1 = ?L2")
proof
show "?L2 ⊆ ?L1" unfolding Lang_def
using derives_fork_if_derives1[of P B1 _ A B2] derives_fork_if_derives1[of P B2 _ A B1]
by (auto simp add: insert_commute)
next
show "?L1 ⊆ ?L2"
unfolding Lang_def using derives_disj_if_derives_fork[OF assms] by auto
qed
lemma Lang_disj_Un2:
assumes "Nts P1 ∩ Nts P2 = {}" "S ∉ Nts(P1 ∪ P2) ∪ {S1,S2}" "S1 ∉ Nts P2" "S2 ∉ Nts P1"
shows "Lang ({(S,[Nt S1]), (S,[Nt S2])} ∪ (P1 ∪ P2)) S = Lang P1 S1 ∪ Lang P2 S2"
proof -
let ?P = "{(S, [Nt S1]), (S, [Nt S2])} ∪ (P1 ∪ P2)"
have "Lang ?P S = Lang (P1 ∪ P2) S1 ∪ Lang (P1 ∪ P2) S2"
using Lang_distrib_eq_Un_Lang2[OF assms(2)] by simp
moreover have "Lang (P1 ∪ P2) S1 = Lang P1 S1" using assms(1,3)
apply(subst Lang_disj_Un1[of P1 P2 S1]) unfolding Nts_Lhss_Rhs_Nts by blast+
moreover have "Lang (P2 ∪ P1) S2 = Lang P2 S2" using assms(1,4)
apply(subst Lang_disj_Un1[of P2 P1 S2]) unfolding Nts_Lhss_Rhs_Nts by blast+
ultimately show ?thesis
by (metis sup_commute)
qed
end