(* Title: Tree Automata Author:PeterLammich<peterdotlammichatuni-muenster.de> Maintainer:PeterLammich<peterdotlammichatuni-muenster.de>
*) section"Tree Automata" theory Ta imports Main Automatic_Refinement.Misc Tree begin text_raw‹>
‹
This theory defines tree automata, tree regular languages and
specifies basic algorithms.
Nondeterministic and deterministic (bottom-up) tree automata are defined.
For non-deterministic tree automata, basic algorithms for membership, union,
intersection, forward and backward reduction, and emptiness check are
specified.
Moreover, a (brute-force) determinization algorithm is specified.
For deterministic tree automata, we specify algorithms for complement
and completion.
Finally, the class of regular languages over a given ranked alphabet is defined
and its standard closure properties are proved.
The specification of the algorithms in this theory is very high-level, and the
specifications are not executable. A bit more specific algorithms are defined
in Section~\ref{sec:absalgo}, and a refinement to executable definitions is
done in Section~\ref{sec:taimpl}. ›
"Basic Definitions"
"Tree Automata"
‹
A tree automata consists of a (finite) set of initial states
and a (finite) set of rules.
A rule has the form ‹q → l q1…qn›,
with the meaning that one can derive ‹ ›
\commentRule deconstruction› fun ere l qs) = q" fun rhsq where "rhsq (q → funre l qs) = l" ―cn\f{ecasao naeinmn xecaedfntnsi fun rule_states where "rule_states (q → ertBasic
― ‹ definition"\<delta>_states\<deltaAreeutomatansistsiniteinitialstates \<comment>\<open>Statesinaetomaton> definition"ta_rstates=_lTA<nion\<delta>_states(ta_rulesTA)" \<comment>\<open>Symbolsoccurringinrules\<close> definition"\<delta>_symbols\<delta>==rhsl`\<delta>"
<omment\<open>Nondeterministic,finitetreeautomaton(NFTA)\<close> localetree_automaton= xes",tree_automaton_rec assumesfinite_rules[simp,intro!:finiteta_rules" assumesfinite_initial[simp,intro!]:"finiteinitialjava.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64 begin reviation=_tial" abbreviationationtionn<delta==ta_rulesTA" abbreviation"Q==ta_rstatesTA end
lemma\<delta>_statesI: assumesA:"(q\<rightarrow>lqs)\<in>\<delta>" shows"q\<in>\<delta>_statesjava.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4 "setqs\<subseteq>\<delta>_states\<delta>" usingA apply(unfold\<delta>_states_def) by(autosplit:ta_rule.splitsimpadd:rule_states_simp)
lemma\<delta>_statesI':"\<lbrakk>(q\<rightarrow>lqs)\<in>\<delta>;qi\<in>setjava.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 >statesI(2)byfast
lemmaaccs_mono:"\<lbrakk>accs\<delta>n proof(inductrule:accs.induct[case_namesstep case(stepqlqs\<delta>n) henceR':"(q\<rightarrow>lqs)\<injava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 fromaccs.introsOFRtepps) hyps[Ftep.ems show?case. qed
contexttree_automaton begin lemmainitial_subset:"ta_initialTA\<subseteq>ta_rstatesTA" by(unfoldta_rstates_def)auto lemmastates_subset:"\<delta>_states(ta_rulesTA)\<subseteq>ta_rstates" by(unfoldta_rstates_def)auto lemmafinite_states[simp,intro!]:"finite(ta_rstatesTA\Longrightarrowaccs\<delta>nq" by(autosimpaddta_rstates_def_states_def intro:finite_rulesfinite_UN_I)
localeutomatonion) fixesA::"('L\<rightharpoonupinterpretajava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 assumesA_finite[simp,intro!]:"finite(domA)" begin abbreviation"F==domA" end
\<comment>\<open>Finitetreeautomatawithrankedalphabet\<close> localeranked_tree_automaton= tree_automaton finite_alphabetA forTA::"('Q,'L)tree_automaton_rec" andA:inductive_setcc\>where assumesranked:(\<>qs)<>\>\<Longrightarrow>Af=omelengthsjava.lang.StringIndexOutOfBoundsException: Index 96 out of bounds for length 96 begin
\<comment>\<open>Onlyjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12 lemmaaccs_is_ranked:"accs\<delta>tq\<Longrightarrow>t\<in>ranked_treesA" apply(induct\delta\<equiv\deltatqrule:accs.induct) apply(ruleranked_trees.intros) apply(autosimpaddet_conv_nthnv_nthnkedd done
\<comment>\<open>Deterministic,(bottom-up)finitetreeautomaton(DFTA\close localedet_tree_automaton=ranked_tree_automatonTAA forTA::"('Q,'L)tree_automaton_rec"and"(q<>l)\<in\<delta>(\<delta>{}java.lang.StringIndexOutOfBoundsException: Index 89 out of bounds for length 89 assumesdeterministic:"\<lbrakk>usings_monoFteppsOF]educe_rules_mono] begin theoremaccs_unique:"\<lbrakk>accs\<delta>tq;accs\<deltaabbreviationta_fwd_reduceTA= unfoldingaccs_laz proof(induct\<delta>\<equiv>\<delta>tqarbitrary:q'rule:accs_laz.induct[case_namesstep]) case(stepqfqstsq') henceI: "(q\<rightarrow>fqs)\<in>\<delta>" "list_all_zip(accs_laz\<delta>)tsqs" "list_all_zip(\<[_reduce_rules_subset] "accs_laz\<delta>(NODEfts)q'" byauto fromI(4)obtainqs'whereA': "(q'\<rightarrow>fqs')Inductively,backwardaccessiblestatescharacterizedfollowsjava.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 "list_all_zip(accs_laz\delta)ts'" by(autoelim!:accs_laz.cases)
fromI(2,3)A'(2)have"list_all_zip(=)qswhere by(autosimpadd:list_all_zip_alt) hence"qs=qs'"by(autosimpadd:laz_eq) withdeterministic[OFI(1),ofq']A'(1)show"q=q'"bysimp qed end
subsubsection"CompleteTreeAutomata"
localecomplete_tree_automaton=det_tree_automatonTAA forTA::"('Q,'L)tree_automaton_rec"andA lemaccs_is_b_accessible:accs\deltaLongrightarrow>q\<>b_accessible<delta" apply(inductrule:accs "\<lbrakk>qs\<in>listsQ;Afapplyassumption begin
\<comment>\<open>InacompleteDFTA,alltreescanbelabeledbysomestate\<close> theoremlabel_all:"t\<in>ranked_treesA\<Longrightarrow>\<exists>q\<in>Q.accs\<delta>tq" proof(inductrule:ranked_trees.induct[case_namesconstr]) case(constrtsf) obtainqswhereQS: "qs\<in>listsQ" "list_all_zip(accs\<delta>)tsqs" [imp]:"ength=lengthts" proof- fromconstr(1)have"\<forall>i<lengthts.\<exists>q.q\<in>Q\<and>accs\<delta>(ts!i)q" by(auto) thus?thesis apply(erule_tacobtain_list_from_elements) applylengthqsjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 apply(autosimpadd:list_all_zip_altset_conv_nth) done qed moreoverfromcomplete[OFQS(1),simplified,OFconstr(2)]obtainq where"(q\<rightarrow>fqs)\<in>\<delta>".. ultimatelyshow?case by(autosimpadd:accs_lazta_rstates_def intro:accs_laz.intros<delta>_statesI) qed
fromcomplete[OFQSO(1)]A(2)obtainqowhere"(qo\<rightarrow>lqso)\<in>\<delta>" byauto withQSO(2)have"((fqo)\<rightarrow>lqs)\<in>ta_rules("\<eltaprod_sng2<elta1r=\deltaprod\delta1{} by(forcesimpadd:ta_remap_def) thus"\<exists>q.q\<rightarrow>lqs\<in>ta_rules(ta_remapfTA)".. qed qed
corollaryaccs_exclusive2: "\<lbrakk>accs(\<delta>\<union>\<delta>')nq;\<delta>_states\<delta>\<inter>\<delta>_states\<delta>'={};q\<in>\<delta>_states\<delta>'\<rbrakk> \<Longrightarrow>accs\<delta>'nq" using
lemma\<delta>_states_reduce_subset: shows"\<delta>_states(reduce_rules\<delta>Q)\<subseteq>\<delta>_states\<delta>\<inter>Q" by(unfold\<delta>_states_defreduce_rules_def) auto
\<comment>\<open>Reducingatreeautomatonpreservesthetreeautomatainvariants\<close> theoremta_reduce_inv:assumesA:"tree_automatonTA" shows"tree_automaton(ta_reduceTAP)" proof- interprettree_automatonTAusingA. show?thesisproof show"finite(ta_rulesdet_tree_automatondetTAAjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 "finite(ta_initial(ta_reduceTAP))" usingfinite_statesfinite_rulesfinite_subset[OFreduce_rules_subset] by(unfoldta_reduce_def)(autosimpadd:Let_def) qed qed lemmareduce_\<delta>_states_rules[simp]: "(ta_rules(ta_reduceTA(\<delta>_states(applysimp_all by(autosimpadd:ta_reduce_def\<delta>_states_defreduce_rules_def)
― ‹ The initial states are forward accessible, and if there is a rule whose lhs-state is forward-accessible, all rhs-states of that rule are forward-accessible, too.› inductive_set f_accessible_alt :: "('Q,'L) ta_rule set ==> 'Q set ==> 'Q set" for δ Q0 where fa_refl: "q0∈Q0 ==> q0 ∈ f_accessible_alt δ Q0" | fa_step: "[ q∈f_accessible_alt δ Q0; (q → l qs)∈δ; q'∈set qs ] ==> q' ∈ f_accessible_alt δ Q0"
lemma (in tree_automaton) f_accessible_in_states: "q∈f_accessible (ta_rules TA) (ta_initial TA) ==> q∈ta_rstates TA" using initial_subset states_subset by (drule_tac f_accessible_subset) (auto)
lemma f_accessible_refl_inter_simp[simp]: "Q ∩ f_accessible r Q = Q" by (unfold f_accessible_alt) (auto intro: fa_refl)
― ‹A qeded
the states that are forward-accessible from @{text q}› lemma accs_reduce_f_acc: "accs δ t q ==> accs (reduce_rules δ (f_accessible δ {q})) t q" proof (induct rule: accs.induct[case_names step]) case (step q l qs δ n) show ?caseproof (rule accs.intros[of q l qs]) show"(q → l qs) ∈ reduce_rules δ (f_accessible δ {q})" using step(1) by (fastforce
intro!: reduce_rulesI
intro: f_succ.intros
simp add: f_accessible_def) next fix i assume A: "i<length qs"
have B: "f_accessible δ {q} 🪙 f_accessible δ {qs!i}"using step.hyps(1) by (force
simp add: A f_accessible_def
intro: converse_rtrancl_into_rtrancl f_succ.intros[where q'="qs!i"]) show"accs (reduce_rules δ (f_accessible δ {q})) (n ! i) (qs ! i)" using accs_mono[OF step.hyps(4)[OF A] reduce_rules_mono[OF B]] . qed (simp_all add: step.hyps(2,3)) qed
― abbreviation"ta_fwd_reduce TA == (ta_reduce TA (f_accessible (ta_rules TA) (ta_initial TA)))"
― ‹Forward-reducing a tree automaton does not change its language› theorem ta_reduce_f_acc[simp]: "ta_lang (ta_fwd_reduce TA) = ta_lang TA" apply (rule sym) apply (unfold ta_reduce_def ta_lang_def) apply (auto simp add: Let_def) apply (rule_tac x=q in bexI) apply (drule accs_reduce_f_acc) apply (rule_tac
P1="(f_accessible (ta_rules TA) {q})" in accs_mono[OF _ reduce_rules_mono]) apply (auto simp add: f_accessible_def) apply (rule_tac x=q in bexI) apply (blast intro: accs_mono[OF _ reduce_rules_subset])
.
text_raw‹\paragraph{Backward Reduction}›
text‹
A state is backward accessible, iff at least one tree is accepted in it.
Inductively, backward accessible states can be characterized as follows:
A state is backward accessible, if it occurs on the left hand side of a
rule, and all states on this rule's right hand side are backward accessible.
b_accessible :: "('Q,'L) ta_rule set ==> 'Q set"
for δ
where
"[ (q → l qs)∈δ; !!x. x∈set qs ==> x∈b_accessible δ ]==> q∈b_accessible δ"
b_accessibleI:
"[(q → l qs)∈δ; set qs ⊆ b_accessible δ]==> q∈b_accessible δ"
by (auto intro: b_accessible.intros)
―
b_accessible_is_accs:
"[ q∈b_accessible (ta_rules TA);
!!t. accs (ta_rules TA) t q ==> P ]==> P"
(induct arbitrary: P rule: b_accessible.induct[case_names IH])
case (IH q l qs)
obtain ts where
A: "∀i<length qs. accs (ta_rules TA) (ts!i) (qs!i)"
"length ts = length qs"
proof -
from IH(3) have "∀x∈set qs. ∃t. accs (ta_rules TA) t x" by auto
hence "∃ts. (∀i<length qs. accs (ta_rules TA) (ts!i) (qs!i)) ∧ length ts = length qs"
proof (induct qs)
case Nil thus ?case by simp
next
case (Cons q qs) then obtain ts where
IHAPP: "∀i<length
L: "length ts = length qs"
by auto
moreover from Cons obtain t where "accs (ta_rules TA) t q" by auto
ultimately have
"∀i<length (q#qs). accs (ta_rules TA) ((t#ts) ! i) ((q#qs) ! i)"
apply auto
apply (case_tac i)
apply auto
done
thus ?case using L by auto
qed
thus thesis by (blast intro: that)
qed
from A show ?case
apply (rule_tac IH(4)[OF accs.intros[OF IH(1)]])
apply auto
done
― ‹All trees remain accepted when reducing the rules to
backward-accessible states›
accs_reduce_b_acc:
"a\delta\Longrightarrow accs(reduce \<delta "
apply (induct rule: accs.induct)
apply (rule accs.intros)
apply (rule reduce_rulesI)
apply assumption
apply (auto)
apply (rule_tac t="NODE f ts" in accs_is_b_accessible)
apply (rule_tac accs.intros)
a
apply (simp only: in_set_conv_nth)
apply (erule_tac exE)
apply (rule_tac t="ts ! i" in accs_is_b_accessible)
apply auto
done
― ‹Shorthand notation for backward-reduction of a tree automaton›
"ta_bwd_reduce TA == (ta_reduce TA (b_accessible (ta_rules TA)))"
― ‹Backwards-reducing a tree automaton does not change its language›
ta_reduce_b_acc[simp]: "ta_lang (ta_bwd_reduce TA) = ta_lang TA"
apply (rule sym)
apply (unfold ta_reduce_def ta_lang_def)
apply (auto simp add: Let_def)
apply (rule_tac x=q in bexI)
apply (blast intro: accs_reduce_b_acc)
apply (blast dest: accs_is_b_accessible)
apply (rule_tac x=q in bexI)
apply (blast intro: accs_mono[OF _ reduce_rules_subset])
.
―
is empty, if and only if no initial state is backwards-accessible.›
empty_if_no_b_accessible:
"ta_lang TA = {} ⟷ ta_initial TA ∩ b_accessible (ta_rules TA) = {}"
by (auto
simp add: ta_lang_def
intro: accs_is_b_accessible b_accessible_is_accs)
"Product Automaton" ‹
The product automaton of two tree automata accepts the intersection
of the languages of the two automata. ›
― ‹Product rule›
r_prod where
"r_prod (q1 → l1 q
― ‹Product rules›
"δ_prod δ1 δ2 == {
r_prod (q1 → l qs1) (q2 → l qs2) | q1 q2 l qs1 qs2.
length qs1 = length qs2 ∧
(q1 → l qs1)∈δ1 ∧
(q2 → l qs2)∈δ2
"
δ_prodI: "[
length qs1 = length qs2;
(q1 → l qs1)∈δ1;
(q2 → l qs2)∈δ2 ] simp ad: complementTA_de)
by (auto simp add: δ_prod_def)
δ_prodE:
"[
r∈δ_prod δ1 δ2;
!!q1 q2 l qs1 qs2. [ length qs1 = length qs2;
(q1 → l qs1)∈δ1;
(q2 → l qs2)∈ -
r = ((q1,q2) → l (zip qs1 qs2)) ]==> P ]==> P"
by (auto simp add: δ_prod_def)
― ‹)
constructed with the two original sets of rules›
δ_prod_sound:
assumes A: "accs (δ_prod δ1 δ2) t (q1,q2)"
shows "accs δhave QSS: "!!. q\inta complem ==>
-
{
fix δ q
assume "accs δ t q" "δ = (δ_prod δ1 δ2)" "q=(q1,q2)"
hence "accs δ1 t q1 ∧ accs δ2 t q2"
by (induct arbitrary: δ1 δ2 q1 q2 rule: accs.induct)
(auto intro: accs.intros simp add: δ_prod_def)
} with A show "accs δ1 t q1" "accs δ2 t q2" by auto
― ‹Any tree that can be constructed with both original sets of rules can also
be constructed with the product rules›
δ_prod_precise:
"[ accs δ1 t q1; accs δ2 t q2 ]==> accs (δ_prod δ1 δ2) t (q1,q2)"
(induct arbitrary: δ2 q2 rule: accs.induct[case_names step])
case (step q1 l qs1 δ1 ts δ2 q2)
note [simp] = step.hyps(2,3)
from step.hyps(2) obtain qs2 where
I2: "(q2 → l qs2)∈δ2"
"!!i. i<length qs2 ==> accs δ2 (ts ! i) (qs2 ! i)" and
[simp]: "length qs2 = length ts"
by (rule_tac accs.cases[OF step.prems]) fastforce
show ?case
proof (rule accs.intros)
from step.hyps(1) I2(1) show
"((q1,q2) → l (zip qs1 qs2))∈δ_prod δ1 δ2" and
[simp]: "length ts = length (zip qs1 qs2)"
by (unfold δ_prod_def) force+
next
fix i
assume L: "i<length (zip qs1 qs2)"
with step.hyps(4)[OF _ I2(2), of i] have
"accs (δ_prod δ1 δ2) (ts ! i) (qs1 ! i, qs2 ! i)"
by simp
also have "(qs1 ! i, qs2 ! i) = zip qs1 qs2 ! i" using L by auto
finally show "accs (δtree_automaton_re where
qed
δ_prod_empty[simp]:
"δ_prod {} δ = {}"
"δ_prod \e_automaton
by (unfold δ_prod_def) auto
‹The next two definitions are solely for technical reasons.
They are required to allow simplification of expressions of the form
@{term "δ_prod (insert r δ1) δ2"} or @{term "δ_prod δ1 (insert r δ2)"},
without making the simplifier loop. ›
"δ_prod_sng1 r δ2 ==
q1→
{ r_prod r (q2 → l qs2) |
q2 qs2. length qs1 = length qs2 ∧ (q2 → l qs2)∈δ2
}"
"δ_prod_sng2 δ1 r ==
case r of (q2 → l qs2) ==>
{ r_prod (q1 → l qs1) r |
q1 qs1. length qs1 = length qs2 ∧ (q1 → l qs1)∈δ1
}"
,i]:
"finite δ1 ==> finite δ2 ==> finite (δ_prod δ1 δ2)"
-
have
"\delta\delta1 δ ⊆ (λ(r1,r2). case r1 of (q1 → l1 qs1) ==>
case r2 of (q2 → l2 qs2) ==>
((q1,q2) → l1 (zip qs1 qs2)))
` (δ1 × δ2)"
by (unfold δ_prod_def) force
moreover assume "finite δ1" "finite δ2"
ultimately show ?thesis
by (metis finite_imageI finite_cartesian_product finite_subset)
ta_prod_correct_aux2:
assumes TA: "tree_automaton TA1" "tree_automaton TA2"
shows "tree_automaton (ta_prod TA1 TA2)"
-
intetac: com TAC A using C .
interpret ta2: tree_automaton TA2 using TA by blast
show ?thesis
apply unfold_locales
apply (unfold ta_prod_def)
apply (auto
intro: ta1.is_subset ta2.is_subset δ_prod_finite
dest: δ_states_cart
simp add: ta1.finite_states ta2.finite_states
ta1.finite_rules ta2.finite_rules)
done
―
of the two original automata› theorem[ assumes TA: "tree_automaton TA1""tree_automaton TA2" shows "ta_lang (ta_prod TA1 TA2) = ta_lang TA1 ∩ ta_lang TA2" "tree_automaton (ta_prod TA1 TA2)" using ta_prod_correct_aux1
ta_prod_correct_aux2[OF TA] by auto
lemma ta_prod_rta: assumes TA: "ranked_tree_automaton TA1 A""ranked_tree_automaton TA2 A" shows"ranked_tree_automaton (ta_prod TA1 TA2) A" proof - interpret ta1: ranked_tree_automaton TA1 A using TA by blast interpret ta2close
subsubsection"Determinization" text‹
We only formalize the brute-force subset construction without reduction.
The basic idea of this construction is to construct an automaton where the
states are sets of original states, and the lhs of a rule consists of all
states that a term with given rhs and function symbol may be labeled by. ›
context ranked_tree_automaton begin
― ‹Left-hand side of subset rule for given symbol and rhs› definition"δss_lhs f ss == { q | q qs. (q →
― ‹Subset construction› inductive_set δss :: "('Q set,'L) ta_rule set" where "[ A f = Some (length ss); ss ∈ lists {s. s ⊆ s = δss_lhs f ss ]==> (s →\in A; L2<in>regular_l A🚫
lemma δssI: assumes A: "A f = Some (length ss)" "ss ∈ lists {s. s ⊆ ta_rstates TAcase (1 TA1 TA2) shows "( (δss_lhs f ss) → f ss) ∈ δss" using δss.intros[where s="(δss_lhs f ss)"] A by auto
lemma δss_subset[simp, intro!]: "δss_lhs f ss ⊆ Q" by (unfold ta_rstates_def δss_lhs_def) (auto intro: δ_statesI)
lemma δss_finite[simp, intro!]: "finite δss" proof - have "δss ⊆∪((λf. (λ `({s. s⊆Q} × (lists {s. s⊆Q} ∩: ) ` F)" (is "_⊆∪((λf. ?tr f ` ?prod f)`F)") proof (intro equalityI subsetI) fix r assume "r∈δss" then obtain f s ss where U: "r=(s → f ss)" "A f = Some (length ss)" "ss∈lists {s. s⊆Q}" "s=δss_lhs f ss" by (force elim!: δss.cases) from U(4) have "s⊆Q" by simp moreover from U(2) have "length ss = the (A f)" by simp ultimately have "(s,ss)∈?prod f" using U(3) by auto hence "(s → f ss)∈?tr f ` ?prod f" by auto moreover from U(2) have "f∈ ultimately show "r∈∪((λf. ?tr f ` ?prod f)`F)" using U(1) by auto qed moreover have "finite …" by (auto intro!: finite_imageI finite_SigmaI lists_of_len_fin) ultimately show ?thesis by (blast intro: finite_subset) qed
lemma δss_det: "[ (q → f qs) ∈ δss; (q' → f by (auto elim!: δss.cases)
lemma δss_accs_sound: assumes A: "accs δ t q" obtains s where "s<>Q" "q∈s" "accs δss t s" proof - have "∃s⊆Q. q∈s ∧ accs_laz δss t s" using A[unfolded accs_laz] proof (induct δ≡δ t q rule: accs_laz.induct[case_names step]) case (step q f qs ts) hence I: "(q → f qs)∈δ" "list_all_zip (accs_laz δ) ts qs" "list_all_zip (λt q. ∃s. s⊆ by simp_all from I(3) obtain ss where SS: "ss ∈ lists {s. s⊆Q}" "list_all_zip (∈) qs ss" "list_all_zip (accs_laz δss) ts ss" by (erule_tac laz_swap_ex) auto from I(2) SS(2) have LEN[simp]: "length qs = length ts" "length ss = length ts" by (auto simp add: list_all_zip_alt) from ranked[OF I(1)] have AF: "A f = Some (length ts)" by simp
from δssI[of f ss, OF _ SS(1)] AF have RULE_S: "((δss_lhs f ss) → f ss) ∈ δss" by simp from accs_laz.intros[OF RULE_S SS(3)] have G1: "accs_laz δss (NODE f ts) (δss_lhs f ss)" . from I(1) SS(2) have "q∈(δss_lhs f ss)" by (auto simp add: δss_lhs_def) thus ?case using G1 by auto qed thus ?thesis apply (elim exE conjE) apply (rule_tac that) apply assumption apply (auto simp add: accs_laz) done qed
lemma δ assumes A: "accs δss t s" "q∈s" shows "accs δ t q" using A unfolding accs_laz proof (induct δ≡δss t s arbitrary: q rule: accs_laz.induct[case_names step]) case (step s f ss ts) hence I: "(s → f ss) ∈ δss" "list_all_zip (accs_laz δss) ts ss" "list_all_zip (λt s. ∀q∈s. accs_laz δ t q) ts ss" "q∈s" by (auto simp add: Ball_def) from I(2) have [simp]: "length ss = length ts" by (simp add: list_all_zip_alt)
from I(1) have SS: "A f = Some (length ts)" "ss ∈ lists {s. s⊆Q}" "s=δss_lhs f ss" by (force elim!: δss.cases)+ from I(4) SS(3) obtain qs where RULE: "(q → f qs) ∈ δ" and QSISS: "list_all_zip (∈) qs ss" by (auto simp add: δss_lhs_def) from I(3) QSISS have CA: "list_all_zip (accs_laz δ) ts qs" by (auto simp add: list_all_zip_alt) from accs_laz.intros[OF RULE CA] show ?case . qed
theorem detTA_lang[simp]: "ta_lang (detTA) = ta_lang TA" apply (unfold ta_lang_def detTA_def) apply safe apply simp_all proof - fix t s assume A: "s⊆Q ∧ s∩Qi ≠ {}" "accs δss t s" from A(1) obtain qi where QI: "qi∈s" "qi∈Qi" by auto
from δss_accs_precise[OF A(2) QI(1)] have "accs δ t qi" . with QI(2) show "∃qi∈Qi. accs δ t qi" by blast next fix t qi assume A: "qi∈Qi" "accs δ t qi" from δss_accs_sound[OF A(2)] obtain s where SS: "s⊆Q" "qi∈s" "accs δss t s" . with A(1) show "∃s⊆Q. s ∩ Qi ≠ {} ∧ accs δss t s" by blast qed lemmas detTA_correct = detTA_is_ta detTA_lang end
subsubsection "Completion" text ‹ To each deterministic tree automaton, rules and states can be added to make it complete, without changing its language. \<close>
context det_tree_automaton begin ― ‹States of the complete automaton› definition "Qcomplete == insert None (Some`Q)"
lemma Qcomplete_finite[simp, intro!]: "finite Qcomplete" by (auto simp add: Qcomplete_def)
― ‹Rules of the complete automaton› definition δcomplete :: "('Q option, 'L) ta_rule set" where "δcomplete == (remap_rule Some ` δ) ∪ { (None → f qs) | f qs. A f = Some (length qs) ∧ qs∈lists Qcomplete ∧¬(∃qo qso. (qo → f qso)∈δ ∧ qs=map Some qso ) }"
with prems have B: "qs∈lists Qcomplete" by (auto simp add: completeTA_def ta_rstates_def)
from A B prems(2) have ?case apply (rule_tac x=None in exI) apply (simp add: completeTA_def δcomplete_def) done } ultimately show ?case by blast qed
theorem completeTA_lang: "ta_lang completeTA = ta_lang TA" proof (intro equalityI subsetI) ― ‹This direction is done by a monotonicity argument› fix t assume "t∈ta_lang TA" then obtain qi where "qi∈Qi" "accs δ t qi" by (auto simp add: ta_lang_def) hence QI: "Some qi ∈ Some`Qi" and ACCS: "accs (remap_rule Some`δ) t (Some qi)" by (auto intro: remap_accs1) have "(remap_rule Some`δ) ⊆ δcomplete" by (unfold δcomplete_def) auto with ACCS have "accs δcomplete t (Some qi)" by (blast dest: accs_mono) thus "t∈ta_lang completeTA" using QI by (auto simp add: ta_lang_def completeTA_def) next fix t assume A: "t∈ta_lang completeTA" then obtain qi where QI: "qi∈Qi" and ACCS: "accs δcomplete t (Some qi)" by (auto simp add: ta_lang_def completeTA_def) moreover { fix qi have "[ accs δcomplete t (Some qi) ]==> accs δ t qi" unfolding accs_laz proof (induct δ≡δcomplete t q≡"Some qi" arbitrary: qi rule: accs_laz.induct[case_names step]) case (step f qs ts qi) hence I: "((Some qi) → f qs) ∈ δcomplete" "list_all_zip (accs_laz δcomplete) ts qs" "list_all_zip (λt q. (∀qo. q=Some qo ⟶ accs_laz δ t qo)) ts qs" by auto from I(1) have "((Some qi) → f qs) ∈ remap_rule Some`δ" by (unfold δcomplete_def) auto then obtain qso where RULE: "(qi → f qso)∈δ" and QSF: "qs=map Some qso" apply (auto) apply (case_tac x) apply auto done from I(3) QSF have ACCS: "list_all_zip (accs_laz δ) ts qso" by (auto simp add: list_all_zip_alt) from accs_laz.intros[OF RULE ACCS] show ?case . qed } ultimately have "accs δ t qi" by blast thus "t∈ta_lang TA" using QI by (auto simp add: ta_lang_def) qed lemmas completeTA_correct = completeTA_is_ta completeTA_lang end
subsubsection "Complement" text ‹ A deterministic, complete tree automaton can be transformed into an automaton accepting the complement language by complementing its initial states. \<close>
context complete_tree_automaton begin
― ‹Complement automaton, i.e. that accepts exactly the trees not accepted by this automaton› definition "complementTA == ( ta_initial = Q - Qi, ta_rules = δ )"
have QSS: "!!q. q∈ta_rstates complementTA ==> q∈Q" by (auto simp add: complementTA_def ta_rstates_def)
show ?T2 apply (unfold_locales) apply (unfold complementTA_def)[4] apply (auto simp add: deterministic ranked intro: complete QSS) done qed
end
subsection "Regular Tree Languages" subsubsection "Definitions"
― ‹Regular languages over alphabet @{text A}› definition regular_languages :: "('L ⇀ nat) ==> 'L tree set set" where "regular_languages A == { ta_lang TA | (TA::(nat,'L) tree_automaton_rec). ranked_tree_automaton TA A }"
lemma rtlE: fixes L :: "'L tree set" assumes A: "L∈regular_languages A" obtains TA::"(nat,'L) tree_automaton_rec" where "L=ta_lang TA" "ranked_tree_automaton TA A" using A that by (unfold regular_languages_def) blast
context ranked_tree_automaton begin
lemma (in ranked_tree_automaton) rtlI[simp]: shows "ta_lang TA ∈ regular_languages A" proof - ― ‹Obtain injective mapping from the finite set of states to the natural numbers› from finite_imp_inj_to_nat_seg[OF finite_states] obtain f :: "'Q ==> nat" where INJMAP: "inj_on f (ta_rstates TA)" by blast ― ‹Remap automaton. The language remains the same.› from remap_lang[OF INJMAP] have LE: "ta_lang (ta_remap f TA) = ta_lang TA" . moreover have "ranked_tree_automaton (ta_remap f TA) A" .. ultimately show ?thesis by (auto simp add: regular_languages_def) qed
text ‹ It is sometimes more handy to obtain a complete, deterministic tree automaton accepting a given regular language. \<close> theorem obtain_complete: obtains TAC::"('Q set option,'L) tree_automaton_rec" where "ta_lang TAC = ta_lang TA" "complete_tree_automaton TAC A" proof - from detTA_correct have DT: "det_tree_automaton detTA A" and [simp]: "ta_lang detTA = ta_lang TA" by simp_all interpret dt: det_tree_automaton detTA A using DT . from dt.completeTA_correct have G: "ta_lang (det_tree_automaton.completeTA detTA A) = ta_lang TA" "complete_tree_automaton (det_tree_automaton.completeTA detTA A) A" by simp_all thus ?thesis by (blast intro: that) qed
end
lemma rtlE_complete: fixes L :: "'L tree set" assumes A: "L∈regular_languages A" obtains TA::"(nat,'L) tree_automaton_rec" where "L=ta_lang TA" "complete_tree_automaton TA A" proof - from rtlE[OF A] obtain TA :: "(nat,'L) tree_automaton_rec" where [simp, symmetric]: "L = ta_lang TA" and RT: "ranked_tree_automaton TA A" .
interpret ta: ranked_tree_automaton TA A using RT .
obtain TAC :: "(nat set option,'L) tree_automaton_rec" where [simp]: "ta_lang TAC = L" and CT: "complete_tree_automaton TAC A" by (rule_tac ta.obtain_complete) auto interpret tac: complete_tree_automaton TAC A using CT .
― ‹Obtain injective mapping from the finite set of states to the natural numbers› from finite_imp_inj_to_nat_seg[OF tac.finite_states] obtain f :: "nat set option ==> nat" where INJMAP: "inj_on f (ta_rstates TAC)" by blast ― ‹Remap automaton. The language remains the same.› from tac.remap_lang[OF INJMAP] have LE: "ta_lang (ta_remap f TAC) = L" by simp have "complete_tree_automaton (ta_remap f TAC) A" using tac.remap_cta[OF INJMAP] . thus ?thesis by (rule_tac that[OF LE[symmetric]]) qed
subsubsection "Closure Properties" text ‹ In this section, we derive the standard closure properties of regular languages, i.e. that regular languages are closed under union, intersection, complement, and difference, as well as that the empty and the universal language are regular. Note that we do not formalize homomorphisms or tree transducers here. \<close> theorem (in finite_alphabet) rtl_empty[simp, intro!]: "{} ∈ regular_languages A" by (rule ranked_tree_automaton.rtlI[OF ta_empty_rta, simplified])
interpret ta1: ranked_tree_automaton TA1 A by simp interpret ta2: ranked_tree_automaton TA2 A by simp
have "ta_lang (ta_union_wrap TA1 TA2) = ta_lang TA1 ∪ ta_lang TA2" apply (rule ta_union_wrap_correct) by unfold_locales with ranked_tree_automaton.rtlI[OF ta_union_wrap_rta[OF TA]] show ?thesis by (simp)
qed theorem rtl_inter_closed: "[L1∈regular_languages A; L2∈regular_languages A]==> L1∩L2 ∈ regular_languages A" proof (elim rtlE, goal_cases) case (1 TA1 TA2) with ta_prod_correct[of TA1 TA2] ta_prod_rta[of TA1 A TA2] have L: "ta_lang (ta_prod TA1 TA2) = L1∩L2" and A: "ranked_tree_automaton (ta_prod TA1 TA2) A" by (simp_all add: ranked_tree_automaton.axioms) show ?thesis using ranked_tree_automaton.rtlI[OF A] by (simp add: L) qed
theorem rtl_complement_closed: "L∈regular_languages A ==> ranked_trees A - L ∈ regular_languages A" proof (elim rtlE_complete, goal_cases) case prems: (1 TA) then interpret ta: complete_tree_automaton TA A by simp from ta.complementTA_correct have [simp]: "ta_lang (ta.complementTA) = ranked_trees A - ta_lang TA" and CTA: "complete_tree_automaton ta.complementTA A" by auto interpret cta: complete_tree_automaton ta.complementTA A using CTA . from cta.rtlI prems(1) show ?case by simp qed
theorem (in finite_alphabet) rtl_univ: "ranked_trees A ∈ regular_languages A" using rtl_complement_closed[OF rtl_empty] by simp
theorem rtl_diff_closed: fixes L1 :: "'L tree set" assumes A[simp]: "L1 ∈ regular_languages A" "L2∈regular_languages A" shows "L1-L2 ∈ regular_languages A" proof - from rtlE[OF A(1)] obtain TA1::"(nat,'L) tree_automaton_rec" where L1: "L1=ta_lang TA1" and RT1: "ranked_tree_automaton TA1 A" . from rtlE[OF A(2)] obtain TA2::"(nat,'L) tree_automaton_rec" where L2: "L2=ta_lang TA2" and RT2: "ranked_tree_automaton TA2 A" .
interpret ta1: ranked_tree_automaton TA1 A using RT1 . interpret ta2: ranked_tree_automaton TA2 A using RT2 .
from ta1.lang_is_ranked have ALT: "L1-L2 = L1 ∩ (ranked_trees A - L2)" by (auto simp add: L1 L2)
show ?thesis unfolding ALT by (simp add: rtl_complement_closed rtl_inter_closed) qed
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.153Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.