Theory Position_Autos
section ‹Framework Instantiations using Marked Regular Expressions›
theory Position_Autos
imports
Automaton
begin
subsection ‹Marked Regular Expressions›
type_synonym 'a mrexp = "(bool * 'a) rexp"
abbreviation "strip ≡ map_rexp snd"
primrec mrexps :: "'a rexp ⇒ ('a mrexp) set" where
"mrexps Zero = {Zero}"
| "mrexps One = {One}"
| "mrexps (Atom a) = {Atom (True, a), Atom (False, a)}"
| "mrexps (Plus r s) = case_prod Plus ` (mrexps r × mrexps s)"
| "mrexps (Times r s) = case_prod Times ` (mrexps r × mrexps s)"
| "mrexps (Star r) = Star ` mrexps r"
lemma finite_mrexps[simp]: "finite (mrexps r)"
by (induction r) auto
lemma strip_mrexps: "strip ` mrexps r = {r}"
by (induction r) (auto simp: set_eq_subset subset_iff image_iff)
fun Lm :: "'a mrexp ⇒ 'a lang" where
"Lm Zero = {}" |
"Lm One = {}" |
"Lm (Atom(m,a)) = (if m then {[a]} else {})" |
"Lm (Plus r s) = Lm r ∪ Lm s" |
"Lm (Times r s) = Lm r @@ lang(strip s) ∪ Lm s" |
"Lm (Star r) = Lm r @@ star(lang(strip r))"
fun final :: "'a mrexp ⇒ bool" where
"final Zero = False" |
"final One = False" |
"final (Atom(m,a)) = m" |
"final (Plus r s) = (final r ∨ final s)" |
"final (Times r s) = (final s ∨ nullable s ∧ final r)" |
"final (Star r) = final r"
abbreviation read :: "'a ⇒ 'a mrexp ⇒ 'a mrexp" where
"read a ≡ map_rexp (λ(m,x). (m ∧ a=x, x))"
lemma read_mrexps[simp]: "r ∈ mrexps s ⟹ read a r ∈ mrexps s"
by (induction s arbitrary: a r) (auto simp: image_iff)
fun follow :: "bool ⇒ 'a mrexp ⇒ 'a mrexp" where
"follow m Zero = Zero" |
"follow m One = One" |
"follow m (Atom(_,a)) = Atom(m,a)" |
"follow m (Plus r s) = Plus (follow m r) (follow m s)" |
"follow m (Times r s) =
Times (follow m r) (follow (final r ∨ m ∧ nullable r) s)" |
"follow m (Star r) = Star(follow (final r ∨ m) r)"
lemma follow_mrexps[simp]: "r ∈ mrexps s ⟹ follow b r ∈ mrexps s"
by (induction s arbitrary: b r) (auto simp: image_iff)
lemma strip_read[simp]: "strip (read a r) = strip r"
by (simp add: map_map_rexp split_def)
lemma Nil_notin_Lm[simp]: "[] ∉ Lm r"
by (induction r) (auto split: if_splits)
lemma Nil_in_lang_strip[simp]: "[] ∈ lang(r) ⟷ [] ∈ lang(strip r)"
by (induction r) auto
lemma strip_follow[simp]: "strip(follow m r) = strip r"
by (induction r arbitrary: m) (auto split: if_splits)
lemma conc_lemma: "[] ∉ A ⟹ {w : A @@ B. w ≠ [] ∧ P(hd w)} = {w : A. w ≠ [] ∧ P(hd w)} @@ B"
unfolding conc_def by auto (metis hd_append2)+
lemma Lm_read: "Lm (read a r) = {w : Lm r. w ≠ [] ∧ hd w = a}"
proof (induction r)
case (Times r1 r2) thus ?case
using conc_lemma[OF Nil_notin_Lm, where P = "λx. x=a" and r1 = r1] by auto
next
case Star thus ?case using conc_lemma[OF Nil_notin_Lm, where P = "λx. x=a"] by simp
qed (auto split: if_splits)
lemma tl_conc[simp]: "[] ∉ A ⟹tl ` (A @@ B) = tl ` A @@ B"
by (fastforce simp: image_def Bex_def tl_append split: list.split)
lemma Nil_in_tl_Lm_if_final[simp]: "final r ⟹ [] : tl ` Lm r"
by (induction r) (auto simp: nullable_iff image_Un)
lemma Nil_notin_tl_if_not_final: "¬ final r ⟹ [] ∉ tl ` Lm r"
by (induction r) (auto simp: nullable_iff Nil_tl singleton_in_conc intro!: image_eqI[rotated])
lemma Lm_follow: "Lm (follow m r) = tl ` Lm r ∪ (if m then lang(strip r) else {}) - {[]}"
proof (induction r arbitrary: m)
case (Atom mb) thus ?case by (cases mb) auto
next
case (Times r s) thus ?case
by (simp add: Un_Diff image_Un conc_Un_distrib nullable_iff
conc_Diff_if_Nil1 Nil_notin_tl_if_not_final Un_ac)
next
case (Star r) thus ?case
by (simp add: Un_Diff conc_Un_distrib
conc_Diff_if_Nil1 Nil_notin_tl_if_not_final star_Diff_Nil_fold)
qed auto
subsection ‹Mark Before Atom›
text‹Position automaton where mark is placed before atoms.›
abbreviation "empty_mrexp ≡ map_rexp (λa. (False,a))"
lemma empty_mrexp_mrexps[simp]: "empty_mrexp r ∈ mrexps r"
by (induction r) auto
lemma nullable_empty_mrexp[simp]: "nullable (empty_mrexp r) = nullable r"
by (induct r) auto
definition "init_b r = (follow True (empty_mrexp r), nullable r)"
lemma init_b_mrexps[simp]: "init_b r ∈ mrexps r × UNIV"
unfolding init_b_def by auto
fun delta_b where
"delta_b a (r,b) = (let r' = read a r in (follow False r', final r'))"
lemma delta_b_mrexps[simp]: "rb ∈ mrexps r × UNIV ⟹ delta_b a rb ∈ mrexps r × UNIV"
by (auto simp: Let_def)
lemma fold_delta_b_init_b_mrexps[simp]: "fold delta_b w (init_b s) ∈ mrexps s × UNIV"
by (induction w arbitrary: s rule: rev_induct) auto
fun L_b where
"L_b (r,b) = Lm r ∪ (if b then {[]} else {})"
abbreviation "final_b ≡ snd"
lemma Lm_empty: "Lm (empty_mrexp r) = {}"
by (induction r) auto
lemma final_read_Lm: "final(read a r) ⟷ [a] ∈ Lm r"
by (induction r) (auto simp: nullable_iff concI_if_Nil2 singleton_in_conc split: if_splits)
global_interpretation before: rexp_DFA init_b delta_b final_b L_b
defines before_closure = before.closure
and check_eqv_b = before.check_eqv
and reachable_b = before.reachable
and automaton_b = before.automaton
and match_b = before.match
proof (standard, goal_cases)
case (1 r) show "L_b (init_b r) = lang r"
by(auto simp add: init_b_def Lm_follow Lm_empty map_map_rexp nullable_iff)
next
case (2 a rb) show "L_b (delta_b a rb) = Deriv a (L_b rb)"
by (cases rb) (auto simp add: Deriv_def final_read_Lm image_def Lm_read Lm_follow)
next
case (3 rb) show "final_b rb ⟷ [] ∈ L_b rb" by (cases rb) simp
next
case (4 s)
have "{fold delta_b w (init_b s) |w. True} ⊆ mrexps s × UNIV"
by (intro subsetI, elim CollectE exE) (simp only: fold_delta_b_init_b_mrexps)
then show "finite {fold delta_b w (init_b s) |w. True}" by (rule finite_subset) simp
qed
subsection ‹Mark After Atom›
text‹Position automaton where mark is placed after atoms. This is the
Glushkov and McNaughton/Yamada construction.›
definition "init_a r = (True, empty_mrexp r)"
lemma init_a_mrexps[simp]: "init_a r ∈ UNIV × mrexps r"
unfolding init_a_def by auto
fun delta_a where
"delta_a a (b,r) = (False, read a (follow b r))"
lemma delta_a_mrexps[simp]: "br ∈ UNIV × mrexps r ⟹ delta_a a br ∈ UNIV × mrexps r"
by auto
lemma fold_delta_a_init_a_mrexps[simp]: "fold delta_a w (init_a s) ∈ UNIV × mrexps s"
by (induction w arbitrary: s rule: rev_induct) auto
fun final_a where
"final_a (b,r) ⟷ final r ∨ b ∧ nullable r"
fun L_a where
"L_a (b,r) = Lm (follow b r) ∪ (if final_a(b,r) then {[]} else {})"
lemma nonfinal_empty_mrexp: "¬ final (empty_mrexp r)"
by (induction r) auto
lemma Cons_eq_tl_iff[simp]: "x # xs = tl ys ⟷ (∃y. ys = y # x # xs)"
by (cases ys) auto
lemma tl_eq_Cons_iff[simp]: "tl ys = x # xs ⟷ (∃y. ys = y # x # xs)"
by (cases ys) auto
global_interpretation after: rexp_DFA init_a delta_a final_a L_a
defines after_closure = after.closure
and check_eqv_a = after.check_eqv
and reachable_a = after.reachable
and automaton_a = after.automaton
and match_a = after.match
proof (standard, goal_cases)
case (1 r) show "L_a (init_a r) = lang r"
by (auto simp: init_a_def nonfinal_empty_mrexp Lm_follow Lm_empty map_map_rexp nullable_iff)
next
case (2 a br) show "L_a (delta_a a br) = Deriv a (L_a br)"
by (cases br) (simp add: Deriv_def final_read_Lm Lm_read Lm_follow,
fastforce simp: image_def neq_Nil_conv)
next
case (3 br) show "final_a br ⟷ [] ∈ L_a br" by (cases br) simp
next
case (4 s)
have "{fold delta_a w (init_a s) |w. True} ⊆ UNIV × mrexps s"
by (intro subsetI, elim CollectE exE) (simp only: fold_delta_a_init_a_mrexps)
then show "finite {fold delta_a w (init_a s) |w. True}" by (rule finite_subset) simp
qed
text ‹
The ``before'' atomaton is a quotient of the ``after'' automaton.
The proof below follows an informal proof given by Helmut Seidl in personal communication.
›
fun hom_ab where
"hom_ab (b, r) = (follow b r, final_a (b, r))"
lemma hom_delta: "hom_ab (delta_a x br) = delta_b x (hom_ab br)"
by(cases br) (auto simp add: Let_def)
lemma hom_deltas: "hom_ab (fold delta_a w br) = fold delta_b w (hom_ab br)"
by (induct w arbitrary: br) (auto simp add: hom_delta)
lemma hom_init: "hom_ab (init_a r) = init_b r"
unfolding init_a_def init_b_def hom_ab.simps by (simp add: nonfinal_empty_mrexp)
lemma reachable_ab: "reachable_b as r = hom_ab ` reachable_a as r"
unfolding after.reachable before.reachable by (force simp: hom_init hom_deltas)
theorem card_reachable_ab: "card (reachable_b as r) ≤ card (reachable_a as r)"
unfolding reachable_ab using after.finite_reachable by (rule card_image_le)
text‹The implementation by Fischer et al.:›
fun shift :: "bool ⇒ 'a mrexp ⇒ 'a ⇒ 'a mrexp" where
"shift _ One _ = One" |
"shift _ Zero _ = Zero" |
"shift m (Atom (_,x)) c = Atom (m ∧ (x=c),x)" |
"shift m (Plus r s) c = Plus (shift m r c) (shift m s c)" |
"shift m (Times r s) c =
Times (shift m r c) (shift (final r ∨ m ∧ nullable r) s c)" |
"shift m (Star r) c = Star (shift (final r ∨ m) r c)"
lemma shift_read_follow: "shift m r x = read x (follow m r)"
by (induction m r x rule: shift.induct) auto
text‹In the spirit of Asperti, and similarly quadratic because of need
to call final1 in move.›
fun final1 :: "'a mrexp ⇒ 'a ⇒ bool" where
"final1 Zero _ = False" |
"final1 One _ = False" |
"final1 (Atom(m,a)) x = (m ∧ a=x)" |
"final1 (Plus r s) x = (final1 r x ∨ final1 s x)" |
"final1 (Times r s) x = (final1 s x ∨ nullable s ∧ final1 r x)" |
"final1 (Star r) x = final1 r x"
fun move :: "'a ⇒ 'a mrexp ⇒ bool ⇒ 'a mrexp" where
"move _ One _ = One" |
"move _ Zero _ = Zero" |
"move c (Atom (_,a)) m = Atom (m, a)" |
"move c (Plus r s) m = Plus (move c r m) (move c s m)" |
"move c (Times r s) m =
Times (move c r m) (move c s (final1 r c ∨ m ∧ nullable r))" |
"move c (Star r) m = Star (move c r (final1 r c ∨ m))"
lemma nullable_read[simp]: "nullable (read c r) = nullable r"
by (induction r) auto
lemma final_read_final1: "final (read c r) = final1 r c"
by (induction r) auto
lemma move_follow_read: "move c r m = follow m (read c r)"
by (induction c r m rule: move.induct) (auto simp: final_read_final1)
end