Theory Pushdown_Automata
section ‹Pushdown Automata (PDA)›
theory Pushdown_Automata
imports Main
begin
subsection ‹Definitions›
text ‹In the following, we define \emph{pushdown automata} and show some basic properties of them.
The formalization is based on the Lean formalization by Leichtfried\cite{lean}.›
text ‹We represent the transition function $\delta$ by splitting it into two different functions
$\delta_1 : Q \times \Sigma \times \Gamma \rightarrow Q \times \Gamma^*$ and
$\delta_2 : Q \times \Gamma \rightarrow Q \times \Gamma^*$,
where $\delta_1(q, a, Z) := \delta(q, a, Z)$ and $\delta_2(q, Z) := \delta(q, \epsilon, Z)$.›
record ('q,'a,'s) pda = init_state :: 'q
init_symbol :: 's
final_states :: "'q set"
delta :: "'q ⇒ 'a ⇒ 's ⇒ ('q × 's list) set"
delta_eps :: "'q ⇒ 's ⇒ ('q × 's list) set"
locale pda =
fixes M :: "('q :: finite, 'a :: finite, 's :: finite) pda"
assumes finite_delta: "finite (delta M p a Z)"
and finite_delta_eps: "finite (delta_eps M p Z)"
begin
notation delta ("δ")
notation delta_eps ("δε")
fun step :: "'q × 'a list × 's list ⇒ ('q × 'a list × 's list) set" where
"step (p, a#w, Z#α) = {(q, w, β@α) | q β. (q, β) ∈ δ M p a Z}
∪ {(q, a#w, β@α) | q β. (q, β) ∈ δε M p Z}"
| "step (p, [], Z#α) = {(q, [], β@α) | q β. (q, β) ∈ δε M p Z}"
| "step (_, _, []) = {}"
fun step⇩1 :: "'q × 'a list × 's list ⇒ 'q × 'a list × 's list ⇒ bool"
("(_ ↝ _)" [50, 50] 50) where
"(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟷ (p⇩2, w⇩2, α⇩2) ∈ step (p⇩1, w⇩1, α⇩1)"
definition steps :: "'q × 'a list × 's list ⇒ 'q × 'a list × 's list ⇒ bool"
("(_ ↝* _)" [50, 50] 50) where
"steps ≡ step⇩1 ^**"
inductive stepn :: "nat ⇒ 'q × 'a list × 's list ⇒ 'q × 'a list × 's list ⇒ bool" where
refl⇩n: "stepn 0 (p, w, α) (p, w, α)" |
step⇩n: "stepn n (p⇩1, w⇩1, α⇩1) (p⇩2, w⇩2, α⇩2) ⟹ step⇩1 (p⇩2, w⇩2, α⇩2) (p⇩3, w⇩3, α⇩3) ⟹ stepn (Suc n) (p⇩1, w⇩1, α⇩1) (p⇩3, w⇩3, α⇩3)"
abbreviation stepsn ("(_ /↝'(_')/ _)" [50, 0, 50] 50) where
"c ↝(n) c' ≡ stepn n c c'"
text ‹The language accepted by empty stack:›
definition accept_stack :: "'a list set" where
"accept_stack ≡ {w. ∃q. (init_state M, w, [init_symbol M]) ↝* (q, [], [])}"
text ‹The language accepted by final state:›
definition accept_final :: "'a list set" where
"accept_final ≡ {w. ∃q ∈ final_states M. ∃γ. (init_state M, w, [init_symbol M]) ↝* (q, [], γ)}"
subsection ‹Basic Lemmas›
subsubsection ‹\<^const>‹step› and \<^const>‹step⇩1››
lemma card_trans_step: "card (δ M p a Z) = card {(q, w, β@α) | q β. (q, β) ∈ δ M p a Z}"
by (rule bij_betw_same_card[where ?f = "λ(q,β). (q, w, β@α)"]) (auto simp: bij_betw_def inj_on_def)
lemma card_eps_step: "card (δε M p Z) = card {(q, w, β@α) | q β. (q, β) ∈ δε M p Z}"
by (rule bij_betw_same_card[where ?f = "λ(q,β). (q, w, β@α)"]) (auto simp: bij_betw_def inj_on_def)
lemma card_empty_step: "card (step (p, [], Z#α)) = card (δε M p Z)"
by (rule sym) (simp add: card_eps_step)
lemma finite_delta_step: "finite {(q, w, β @ α) |q β. (q, β) ∈ δ M p a Z}" (is "finite ?A")
using bij_betw_finite[of "λ(q,β). (q, w, β@α)" "δ M p a Z" ?A] by (fastforce simp add: bij_betw_def inj_on_def finite_delta)
lemma finite_delta_eps_step: "finite {(q, w, β @ α) |q β. (q, β) ∈ δε M p Z}" (is "finite ?A")
using bij_betw_finite[of "λ(q,β). (q, w, β@α)" "δε M p Z" ?A] by (fastforce simp add: bij_betw_def inj_on_def finite_delta_eps)
lemma card_nonempty_step: "card (step (p, a#w, Z#α)) = card (δ M p a Z) + card (δε M p Z)"
apply (simp only: step.simps)
apply (subst card_trans_step)
apply (subst card_eps_step)
apply (rule card_Un_disjoint)
apply (auto simp: finite_delta_step finite_delta_eps_step)
done
lemma finite_step: "finite (step (p, w, Z#α))"
by (cases w) (auto simp: finite_delta_step finite_delta_eps_step)
lemma step⇩1_nonempty_stack: "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟹ ∃Z' α'. α⇩1 = Z'#α'"
by (cases α⇩1) auto
lemma step⇩1_empty_stack: "¬ (p⇩1, w⇩1, []) ↝ (p⇩2, w⇩2, α⇩2)"
by simp
lemma step⇩1_rule: "(p⇩1, w⇩1, Z#α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟷ (∃β. w⇩2 = w⇩1 ∧ α⇩2 = β@α⇩1 ∧ (p⇩2, β) ∈ δε M p⇩1 Z)
∨ (∃a β. w⇩1 = a # w⇩2 ∧ α⇩2 = β@α⇩1 ∧ (p⇩2, β) ∈ δ M p⇩1 a Z)"
by (cases w⇩1) auto
lemma step⇩1_rule_ext: "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟷ (∃Z' α'. α⇩1 = Z'#α' ∧ ((∃β. w⇩2 = w⇩1 ∧ α⇩2 = β@α' ∧ (p⇩2, β) ∈ δε M p⇩1 Z')
∨ (∃a β. w⇩1 = a # w⇩2 ∧ α⇩2 = β@α' ∧ (p⇩2, β) ∈ δ M p⇩1 a Z')))" (is "?l ⟷ ?r")
apply (rule iffI)
apply (metis step⇩1_nonempty_stack step⇩1_rule)
apply (use step⇩1_rule in force)
done
lemma step⇩1_stack_app: "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟹ (p⇩1, w⇩1, α⇩1 @ γ) ↝ (p⇩2, w⇩2, α⇩2 @ γ)"
using step⇩1_rule_ext by auto
subsubsection ‹\<^const>‹steps››
lemma steps_refl: "(p, w, α) ↝* (p, w, α)"
by (simp add: steps_def)
lemma steps_trans: "⟦ (p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2); (p⇩2, w⇩2, α⇩2) ↝* (p⇩3, w⇩3, α⇩3) ⟧
⟹ (p⇩1, w⇩1, α⇩1) ↝* (p⇩3, w⇩3, α⇩3)"
unfolding steps_def using rtranclp_trans[where ?r = step⇩1] by blast
lemma step⇩1_steps: "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟹ (p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2)"
by (simp add: steps_def r_into_rtranclp)
lemma steps_empty_stack: "(p⇩1, w⇩1, []) ↝* (p⇩2, w⇩2, α⇩2) ⟹ p⇩1 = p⇩2 ∧ w⇩1 = w⇩2 ∧ α⇩2 = []"
unfolding steps_def using converse_rtranclpE2 by fastforce
lemma steps_induct2[consumes 1]:
assumes "x1 ↝* x2"
and "⋀p w α. P (p, w, α) (p, w, α)"
and "⋀p⇩1 w⇩1 α⇩1 p⇩2 w⇩2 α⇩2 p⇩3 w⇩3 α⇩3. (p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟹ (p⇩2, w⇩2, α⇩2) ↝* (p⇩3, w⇩3, α⇩3) ⟹
P (p⇩2, w⇩2, α⇩2) (p⇩3, w⇩3, α⇩3) ⟹ P (p⇩1, w⇩1, α⇩1) (p⇩3, w⇩3, α⇩3)"
shows "P x1 x2"
using assms[unfolded steps_def]
proof(induction rule: converse_rtranclp_induct)
case base thus ?case by (metis prod_cases3)
next
case step thus ?case by simp (metis prod_cases3 step⇩1.simps)
qed
lemma steps_induct2_bw[consumes 1, case_names base step]:
assumes "steps x1 x2"
and "⋀p w α. P (p, w, α) (p, w, α)"
and "⋀p⇩1 w⇩1 α⇩1 p⇩2 w⇩2 α⇩2 p⇩3 w⇩3 α⇩3. (p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2) ⟹ (p⇩2, w⇩2, α⇩2) ↝ (p⇩3, w⇩3, α⇩3) ⟹
P (p⇩1, w⇩1, α⇩1) (p⇩2, w⇩2, α⇩2) ⟹ P (p⇩1, w⇩1, α⇩1) (p⇩3, w⇩3, α⇩3)"
shows "P x1 x2"
using assms[unfolded steps_def]
proof(induction rule: rtranclp_induct)
case base
then show ?case by (metis prod_cases3)
next
case (step)
then show ?case by simp (metis prod_cases3 step⇩1.simps)
qed
lemmas converse_rtranclp_induct3_aux =
converse_rtranclp_induct [of step⇩1 "(ax, ay, az)" "(bx, by, bz)", split_rule]
lemmas steps_induct =
converse_rtranclp_induct3_aux [of M, folded steps_def,consumes 1, case_names refl step]
lemma step⇩1_word_app: "step⇩1 (p⇩1, w⇩1, α⇩1) (p⇩2, w⇩2, α⇩2) ⟷ step⇩1 (p⇩1, w⇩1 @ w, α⇩1) (p⇩2, w⇩2 @ w, α⇩2)"
using step⇩1_rule_ext by simp
lemma decreasing_word: "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2) ⟹ ∃w. w⇩1 = w @ w⇩2"
by (induction rule: steps_induct) (use step⇩1_rule_ext in auto)
subsubsection ‹\<^const>‹stepn››
inductive_cases stepn_zeroE[elim!]: "(p⇩1, w⇩1, α⇩1) ↝(0) (p⇩2, w⇩2, α⇩2)"
thm stepn_zeroE
inductive_cases stepn_sucE[elim!]: "(p⇩1, w⇩1, α⇩1) ↝(Suc n) (p⇩2, w⇩2, α⇩2)"
thm stepn_sucE
declare stepn.intros[simp, intro]
lemma step⇩1_stepn_one: "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟷ (p⇩1, w⇩1, α⇩1) ↝(1) (p⇩2, w⇩2, α⇩2)"
by auto
lemma stepn_split_last: "(∃p' w' α'. (p⇩1, w⇩1, α⇩1) ↝(n) (p', w', α') ∧ (p', w', α') ↝ (p⇩2, w⇩2, α⇩2))
⟷ (p⇩1, w⇩1, α⇩1) ↝(Suc n) (p⇩2, w⇩2, α⇩2)"
by auto
lemma stepn_split_first: "(∃p' w' α'. (p⇩1, w⇩1, α⇩1) ↝ (p', w', α') ∧ (p', w', α') ↝(n) (p⇩2, w⇩2, α⇩2))
⟷ (p⇩1, w⇩1, α⇩1) ↝(Suc n) (p⇩2, w⇩2, α⇩2)" (is "?l ⟷ ?r")
proof
assume ?l
then obtain p' w' α' where r1: "(p⇩1, w⇩1, α⇩1) ↝ (p', w', α')" and rN: "(p', w', α') ↝(n) (p⇩2, w⇩2, α⇩2)" by blast
from rN r1 show ?r
by (induction rule: stepn.induct) auto
next
show "?r ⟹ ?l"
by (induction "Suc n" "(p⇩1, w⇩1, α⇩1)" "(p⇩2, w⇩2, α⇩2)" arbitrary: n p⇩2 w⇩2 α⇩2 rule: stepn.induct)
(metis old.nat.exhaust refl⇩n step⇩n stepn_zeroE)
qed
lemma stepn_induct[consumes 1, case_names basen stepn]:
assumes "x1 ↝(n) x2"
and "⋀p w α. P 0 (p, w, α) (p, w, α)"
and "⋀n p⇩1 w⇩1 α⇩1 p⇩2 w⇩2 α⇩2 p⇩3 w⇩3 α⇩3. (p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2) ⟹ (p⇩2, w⇩2, α⇩2) ↝(n) (p⇩3, w⇩3, α⇩3) ⟹
P n (p⇩2, w⇩2, α⇩2) (p⇩3, w⇩3, α⇩3) ⟹ P (Suc n) (p⇩1, w⇩1, α⇩1) (p⇩3, w⇩3, α⇩3)"
shows "P n x1 x2"
using assms proof (induction n arbitrary: x1)
case 0
obtain p⇩1 w⇩1 α⇩1 p⇩2 w⇩2 α⇩2 where [simp]: "x1 = (p⇩1, w⇩1, α⇩1)" and [simp]: "x2 = (p⇩2, w⇩2, α⇩2)"
by (metis prod_cases3)
from "0.prems"(1) have "x1 = x2" by auto
with "0.prems"(2) show ?case by simp
next
case (Suc n)
obtain p⇩1 w⇩1 α⇩1 p⇩2 w⇩2 α⇩2 where [simp]: "x1 = (p⇩1, w⇩1, α⇩1)" and x2_def[simp]: "x2 = (p⇩2, w⇩2, α⇩2)"
by (metis prod_cases3)
from Suc.prems(1) obtain p' w' α' where
r1: "(p⇩1, w⇩1, α⇩1) ↝ (p', w', α')" and rN: "(p', w', α') ↝(n) (p⇩2, w⇩2, α⇩2)"
using stepn_split_first[of p⇩1 w⇩1 α⇩1 n p⇩2 w⇩2 α⇩2] by auto
have "P n (p', w', α') (p⇩2, w⇩2, α⇩2)"
using Suc.IH[unfolded x2_def, OF rN Suc.prems(2,3)] by simp
then show ?case
using Suc.prems(3)[OF r1 rN] by simp
qed
lemma stepn_trans:
assumes "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2)"
and "(p⇩2, w⇩2, α⇩2) ↝(m) (p⇩3, w⇩3, α⇩3)"
shows "(p⇩1, w⇩1, α⇩1) ↝(n+m) (p⇩3, w⇩3, α⇩3)"
using assms(2,1) by (induction rule: stepn.induct) auto
lemma stepn_steps: "(∃n. (p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2)) ⟷ (p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2)" (is "?l ⟷ ?r")
proof
assume ?l
then obtain n where "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2)" by blast
thus "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2)"
apply (induction rule: stepn.induct)
apply (rule steps_refl)
apply (simp add: step⇩1_steps steps_trans)
done
next
show "?r ⟹ ?l"
by (induction rule: steps_induct) (use stepn_split_first in blast)+
qed
lemma stepn_word_app: "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2) ⟷ (p⇩1, w⇩1 @ w, α⇩1) ↝(n) (p⇩2, w⇩2 @ w, α⇩2)" (is "?l ⟷ ?r")
proof
show "?l ⟹ ?r"
by (induction n "(p⇩1, w⇩1, α⇩1)" "(p⇩2, w⇩2, α⇩2)" arbitrary: p⇩2 w⇩2 α⇩2 rule: stepn.induct) (use step⇩1_word_app in auto)
next
show "?r ⟹ ?l"
proof (induction n "(p⇩1, w⇩1 @ w, α⇩1)" "(p⇩2, w⇩2 @ w, α⇩2)" arbitrary: p⇩2 w⇩2 α⇩2 rule: stepn.induct)
case (step⇩n n p⇩2 w⇩2 α⇩2 p⇩3 α⇩3 w⇩3)
obtain w' where w⇩2_def: "w⇩2 = w' @ w⇩3 @ w"
using decreasing_word[OF step⇩1_steps[OF step⇩n(3)]] by blast
with step⇩n(2) have "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w' @ w⇩3, α⇩2)" by simp
moreover from step⇩n(3) w⇩2_def have "(p⇩2, w' @ w⇩3, α⇩2) ↝ (p⇩3, w⇩3, α⇩3)"
using step⇩1_word_app by force
ultimately show ?case by simp
qed simp
qed
lemma steps_word_app: "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2) ⟷ (p⇩1, w⇩1 @ w, α⇩1) ↝* (p⇩2, w⇩2 @ w, α⇩2)"
using stepn_steps stepn_word_app by metis
lemma stepn_not_refl_split_first:
assumes "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2)"
and "(p⇩1, w⇩1, α⇩1) ≠ (p⇩2, w⇩2, α⇩2)"
shows "∃n' p' w' α'. n = Suc n' ∧ (p⇩1, w⇩1, α⇩1) ↝ (p', w', α') ∧ (p', w', α') ↝(n') (p⇩2, w⇩2, α⇩2)"
proof -
from assms have "n > 0" by fast
then obtain n' where "n = Suc n'"
using not0_implies_Suc by blast
with assms(1) show ?thesis
using stepn_split_first by simp
qed
lemma stepn_not_refl_split_last:
assumes "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2)"
and "(p⇩1, w⇩1, α⇩1) ≠ (p⇩2, w⇩2, α⇩2)"
shows "∃n' p' w' α'. n = Suc n' ∧ (p⇩1, w⇩1, α⇩1) ↝(n') (p', w', α') ∧ (p', w', α') ↝ (p⇩2, w⇩2, α⇩2)"
proof -
from assms have "n > 0" by fast
then obtain n' where "n = Suc n'"
using not0_implies_Suc by blast
with assms(1) show ?thesis
using stepn_split_last by simp
qed
lemma steps_not_refl_split_first:
assumes "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2)"
and "(p⇩1, w⇩1, α⇩1) ≠ (p⇩2, w⇩2, α⇩2)"
shows "∃p' w' α'. (p⇩1, w⇩1, α⇩1) ↝ (p', w', α') ∧ (p', w', α') ↝* (p⇩2, w⇩2, α⇩2)"
using assms stepn_steps stepn_not_refl_split_first by metis
lemma steps_not_refl_split_last:
assumes "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2)"
and "(p⇩1, w⇩1, α⇩1) ≠ (p⇩2, w⇩2, α⇩2)"
shows "∃p' w' α'. (p⇩1, w⇩1, α⇩1) ↝* (p', w', α') ∧ (p', w', α') ↝ (p⇩2, w⇩2, α⇩2)"
using assms stepn_steps stepn_not_refl_split_last by metis
lemma stepn_stack_app: "(p⇩1, w⇩1, α⇩1) ↝(n) (p⇩2, w⇩2, α⇩2) ⟹ (p⇩1, w⇩1, α⇩1 @ β) ↝(n) (p⇩2, w⇩2, α⇩2 @ β)"
by (induction n "(p⇩1, w⇩1, α⇩1)" "(p⇩2, w⇩2, α⇩2)" arbitrary: p⇩2 w⇩2 α⇩2 rule: stepn.induct) (fastforce intro: step⇩1_stack_app)+
lemma steps_stack_app: "(p⇩1, w⇩1, α⇩1) ↝* (p⇩2, w⇩2, α⇩2) ⟹ (p⇩1, w⇩1, α⇩1 @ β) ↝* (p⇩2, w⇩2, α⇩2 @ β)"
using stepn_steps stepn_stack_app by metis
lemma step⇩1_stack_drop:
assumes "(p⇩1, w⇩1, α⇩1 @ γ) ↝ (p⇩2, w⇩2, α⇩2 @ γ)"
and "α⇩1 ≠ []"
shows "(p⇩1, w⇩1, α⇩1) ↝ (p⇩2, w⇩2, α⇩2)"
proof -
from assms(1) obtain Z' α' where α⇩1_γ_def: "α⇩1 @ γ = Z' # α'" and
rule: "(∃β. w⇩2 = w⇩1 ∧ α⇩2@γ = β@α' ∧ (p⇩2, β) ∈ δε M p⇩1 Z')
∨ (∃a β. w⇩1 = a # w⇩2 ∧ α⇩2@γ = β@α' ∧ (p⇩2,β) ∈ δ M p⇩1 a Z')"
using step⇩1_rule_ext by auto
from α⇩1_γ_def assms(2) obtain α'' where α⇩1_def: "α⇩1 = Z' # α''" and α'_def: "α' = α'' @ γ"
using Cons_eq_append_conv[of Z' α' α⇩1 γ] by auto
from rule α'_def have "(∃β. w⇩2 = w⇩1 ∧ α⇩2 = β@α'' ∧ (p⇩2, β) ∈ δε M p⇩1 Z')
∨ (∃a β. w⇩1 = a # w⇩2 ∧ α⇩2 = β@α'' ∧ (p⇩2,β) ∈ δ M p⇩1 a Z')" by auto
with α⇩1_def show ?thesis
using step⇩1_rule by simp
qed
lemma stepn_reads_input:
assumes "(p⇩1, a # w, α⇩1) ↝(n) (p⇩2, [], α⇩2)"
shows "∃n' k q⇩1 q⇩2 γ⇩1 γ⇩2. n = Suc n' ∧ k ≤ n' ∧ (p⇩1, a # w, α⇩1) ↝(k) (q⇩1, a # w, γ⇩1) ∧
(q⇩1, a # w, γ⇩1) ↝ (q⇩2, w, γ⇩2) ∧ (q⇩2, w, γ⇩2) ↝(n'-k) (p⇩2, [], α⇩2)"
using assms proof (induction n "(p⇩1, a # w, α⇩1)" "(p⇩2, [] :: 'a list, α⇩2)" arbitrary: p⇩1 α⇩1 rule: stepn_induct)
case (stepn n p⇩1 α⇩1 p' w' α')
from stepn(1) have case_dist: "w' = w ∨ w' = a#w" (is "?l ∨ ?r")
using step⇩1_rule_ext by auto
show ?case proof (rule disjE[OF case_dist])
assume l: ?l
from l stepn(1) have "step⇩1 (p⇩1, a # w, α⇩1) (p', w, α')" by simp
moreover from l stepn(2) have "(p', w, α') ↝(n) (p⇩2, [], α⇩2)" by simp
ultimately show ?case by fastforce
next
assume r: ?r
obtain n' k q⇩1 q⇩2 γ⇩1 γ⇩2 where IH1: "n = Suc n'" and IH2: "k ≤ n'" and
IH3: "(p', a # w, α') ↝(k) (q⇩1, a # w, γ⇩1)" and IH4: "(q⇩1, a # w, γ⇩1) ↝ (q⇩2, w, γ⇩2)" and
IH5: "(q⇩2, w, γ⇩2) ↝(n'-k) (p⇩2, [], α⇩2)"
using stepn(3)[OF r] by blast
from IH1 IH2 have "Suc k ≤ n" by simp
moreover from stepn(1) r IH3 have "(p⇩1, a # w, α⇩1) ↝(Suc k) (q⇩1, a # w, γ⇩1)"
using stepn_split_first by blast
moreover from IH1 IH5 have "stepn (n - Suc k) (q⇩2, w, γ⇩2) (p⇩2, [], α⇩2)" by simp
ultimately show ?case
using IH4 by metis
qed
qed
lemma split_word:
"(p⇩1, w @ w', α⇩1) ↝(n) (p⇩2, [], α⇩2) ⟹ ∃k q γ. k ≤ n ∧ (p⇩1, w, α⇩1) ↝(k) (q, [], γ) ∧ (q, w', γ) ↝(n-k) (p⇩2, [], α⇩2)"
proof (induction w arbitrary: n p⇩1 α⇩1)
case (Cons a w)
from Cons(2) obtain n' k q⇩1 q⇩2 γ⇩1 γ⇩2 where n_def: "n = Suc n'" and k_lesseq_n': "k ≤ n'" and stepk: "(p⇩1, a # (w @ w'), α⇩1) ↝(k) (q⇩1, a # (w @ w'), γ⇩1)" and
step1: "(q⇩1, a # (w @ w'), γ⇩1) ↝ (q⇩2, w @ w', γ⇩2)" and stepnk: "(q⇩2, w @ w', γ⇩2) ↝(n'-k) (p⇩2, [], α⇩2)"
using stepn_reads_input[of n p⇩1 a "w @ w'" α⇩1 p⇩2 α⇩2] by auto
obtain k'' q γ where k''_lesseq_n'k: "k'' ≤ n'-k" and stepk'': "(q⇩2, w, γ⇩2) ↝(k'') (q, [], γ)" and stepn'kk'': "(q, w', γ) ↝(n'-k-k'') (p⇩2, [], α⇩2)"
using Cons.IH[OF stepnk] by blast
from stepk step1 have stepSuck: "stepn (Suc k) (p⇩1, a # w, α⇩1) (q⇩2, w, γ⇩2)"
using stepn_word_app[of "Suc k" p⇩1 "a # w" α⇩1 q⇩2 w γ⇩2 w'] by simp
have "(p⇩1, a # w, α⇩1) ↝(Suc k + k'') (q, [], γ)"
using stepn_trans[OF stepSuck stepk''] .
moreover from n_def stepn'kk'' have "(q, w', γ) ↝(n - (Suc k + k'')) (p⇩2, [], α⇩2)" by simp
moreover from n_def k_lesseq_n' k''_lesseq_n'k have "Suc k + k'' ≤ n" by simp
ultimately show ?case by blast
qed fastforce
lemma split_stack:
"stepn n (p⇩1, w⇩1, α⇩1 @ β⇩1) (p⇩2, [], []) ⟹ ∃p' m⇩1 m⇩2 y y'. w⇩1 = y @ y' ∧ m⇩1 + m⇩2 = n
∧ (p⇩1, y, α⇩1) ↝(m⇩1) (p', [], []) ∧ (p', y', β⇩1) ↝(m⇩2) (p⇩2, [], [])"
proof (induction n arbitrary: p⇩1 w⇩1 α⇩1)
case (Suc n)
show ?case proof (cases α⇩1)
case Nil
from Nil have "stepn 0 (p⇩1, [], α⇩1) (p⇩1, [], [])" by simp
moreover from Suc.prems Nil have "stepn (Suc n) (p⇩1, w⇩1, β⇩1) (p⇩2, [], [])" by simp
ultimately show ?thesis by force
next
case (Cons Z α)
with Suc.prems obtain p' w' α' where r1: "step⇩1 (p⇩1, w⇩1, Z # α @ β⇩1) (p', w', α')" and rN: "stepn n (p', w', α') (p⇩2, [], [])"
using stepn_split_first[of p⇩1 w⇩1 "Z # α @ β⇩1" n p⇩2 "[]" "[]"] by auto
from r1 have rule: "(∃β. w' = w⇩1 ∧ α' = β @ α @ β⇩1 ∧ (p', β) ∈ δε M p⇩1 Z)
∨ (∃a β. w⇩1 = a # w' ∧ α' = β @ α @ β⇩1 ∧ (p',β) ∈ δ M p⇩1 a Z)" (is "?l ∨ ?r")
using step⇩1_rule by blast
show ?thesis proof (rule disjE[OF rule])
assume ?l
then obtain β where w1_def: "w⇩1 = w'" and α'_def: "α' = β @ α @ β⇩1" and e: "(p',β) ∈ δε M p⇩1 Z" by blast
from rN α'_def have rN2: "stepn n (p', w', (β @ α) @ β⇩1) (p⇩2, [], [])" by simp
obtain p'' m⇩1 m⇩2 y y' where w'_def: "w' = y @ y'" and m1_m2_n: "m⇩1 + m⇩2 = n"
and rm1: "stepn m⇩1 (p', y, β @ α) (p'', [], [])" and rm2: "stepn m⇩2 (p'', y', β⇩1) (p⇩2, [], [])"
using Suc.IH[OF rN2] by blast
from e have s1: "step⇩1 (p⇩1, y, Z#α) (p', y, β@α)"
using step⇩1_rule by blast
from w1_def w'_def have "w⇩1 = y @ y'" by simp
moreover from m1_m2_n have "Suc m⇩1 + m⇩2 = Suc n" by simp
moreover from s1 rm1 Cons have "stepn (Suc m⇩1) (p⇩1, y, α⇩1) (p'', [], [])"
using stepn_split_first by blast
ultimately show ?thesis
using rm2 by metis
next
assume ?r
then obtain a β where w1_def: "w⇩1 = a # w'" and α'_def: "α' = β @ α @ β⇩1" and tr: "(p',β) ∈ δ M p⇩1 a Z" by blast
from rN α'_def have rN2: "stepn n (p', w', (β @ α) @ β⇩1) (p⇩2, [], [])" by simp
obtain p'' m⇩1 m⇩2 y y' where w'_def: "w' = y @ y'" and m1_m2_n: "m⇩1 + m⇩2 = n"
and rm1: "stepn m⇩1 (p', y, β @ α) (p'', [], [])" and rm2: "stepn m⇩2 (p'', y', β⇩1) (p⇩2, [], [])"
using Suc.IH[OF rN2] by blast
from tr have s1: "step⇩1 (p⇩1, a#y, Z#α) (p', y, β@α)" by simp
from w1_def w'_def have "w⇩1 = (a # y) @ y'" by simp
moreover from m1_m2_n have "Suc m⇩1 + m⇩2 = Suc n" by simp
moreover from s1 rm1 Cons have "stepn (Suc m⇩1) (p⇩1, a#y, α⇩1) (p'', [], [])"
using stepn_split_first by blast
ultimately show ?thesis
using rm2 by metis
qed
qed
qed blast
end
end