Theory Pair_Automaton

theory Pair_Automaton
imports Tree_Automata_Complement GTT_Compose
theory Pair_Automaton
  imports TR.Tree_Automata_Complement UL.Basic_Utils GTT_Compose
begin

definition pair_at_lang :: "('q, 'f) gtt โ‡’ ('q ร— 'q) fset โ‡’ 'f gterm rel" where
  "pair_at_lang ๐’ข Q = {(s, t) | s t p q. q |โˆˆ| gta_der (fst ๐’ข) s โˆง p |โˆˆ| gta_der (snd ๐’ข) t โˆง (q, p) |โˆˆ| Q}"

lemma pair_at_lang_restr_states:
  "pair_at_lang ๐’ข Q = pair_at_lang ๐’ข (Q |โˆฉ| (๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)))"
  by (auto simp: pair_at_lang_def gta_der_def) (meson gterm_ta_der_states) 

lemma pair_at_langE:
  assumes "(s, t) โˆˆ pair_at_lang ๐’ข Q"
  obtains q p where "(q, p) |โˆˆ| Q" and "q |โˆˆ| gta_der (fst ๐’ข) s" and "p |โˆˆ| gta_der (snd ๐’ข) t"
  using assms by (auto simp: pair_at_lang_def)

lemma pair_at_langI:
  assumes "q |โˆˆ| gta_der (fst ๐’ข) s" "p |โˆˆ| gta_der (snd ๐’ข) t" "(q, p) |โˆˆ| Q"
  shows "(s, t) โˆˆ pair_at_lang ๐’ข Q"
  using assms by (auto simp: pair_at_lang_def)

lemma pair_at_lang_fun_states:
  assumes "finj_on f (๐’ฌ (fst ๐’ข))" and "finj_on g (๐’ฌ (snd ๐’ข))"
    and "Q |โІ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)"
  shows "pair_at_lang ๐’ข Q = pair_at_lang (map_prod (fmap_states_ta f) (fmap_states_ta g) ๐’ข) (map_prod f g |`| Q)"
    (is "?LS = ?RS")
proof
  {fix s t assume "(s, t) โˆˆ ?LS"
    then have "(s, t) โˆˆ ?RS" using ta_der_fmap_states_ta_mono[of f "fst ๐’ข" s]
      using ta_der_fmap_states_ta_mono[of g "snd ๐’ข" t]
      by (force simp: gta_der_def map_prod_def image_iff  elim!: pair_at_langE split: prod.split intro!: pair_at_langI)}
  then show "?LS โІ ?RS" by auto
next
  {fix s t assume "(s, t) โˆˆ ?RS"
    then obtain p q where rs: "p |โˆˆ| ta_der (fst ๐’ข) (term_of_gterm s)" "f p |โˆˆ| ta_der (fmap_states_ta f (fst ๐’ข)) (term_of_gterm s)" and
      ts: "q |โˆˆ| ta_der (snd ๐’ข) (term_of_gterm t)" "g q |โˆˆ| ta_der (fmap_states_ta g (snd ๐’ข)) (term_of_gterm t)" and
      st: "(f p, g q) |โˆˆ| (map_prod f g |`| Q)" using assms ta_der_fmap_states_inv[of f "fst ๐’ข" _ s]
      using ta_der_fmap_states_inv[of g "snd ๐’ข" _ t]
      by (auto simp: gta_der_def adapt_vars_term_of_gterm elim!: pair_at_langE)
         (metis (no_types, hide_lams) fimageE fmap_prod_fimageI ta_der_fmap_states_conv)
    then have "p |โˆˆ| ๐’ฌ (fst ๐’ข)" "q |โˆˆ| ๐’ฌ (snd ๐’ข)" by auto
    then have "(p, q) |โˆˆ| Q" using assms st unfolding fimage_iff fBex_def
      by (auto dest!: fsubsetD simp: finj_on_eq_iff)
    then have "(s, t) โˆˆ ?LS" using st rs(1) ts(1) by (auto simp: gta_der_def intro!: pair_at_langI)}
  then show "?RS โІ ?LS" by auto
qed

lemma converse_pair_at_lang:
  "(pair_at_lang ๐’ข Q)ยฏ = pair_at_lang (prod.swap ๐’ข) (Q|ยฏ|)"
  by (auto simp: pair_at_lang_def)

lemma pair_at_agtt:
  "agtt_lang ๐’ข = pair_at_lang ๐’ข (fId_on (gtt_interface ๐’ข))"
  by (auto simp: agtt_lang_def gtt_interface_def pair_at_lang_def gtt_states_def gta_der_def fId_on_iff)

definition ฮ”_eps_pair where
  "ฮ”_eps_pair ๐’ข1 Q1 ๐’ข2 Q2 โ‰ก  Q1 |O| ฮ”ฮต (snd ๐’ข1) (fst ๐’ข2) |O| Q2"

lemma pair_comp_sound1:
  assumes "(s, t) โˆˆ pair_at_lang ๐’ข1 Q1"
    and "(t, u) โˆˆ pair_at_lang ๐’ข2 Q2"
  shows "(s, u) โˆˆ pair_at_lang (fst ๐’ข1, snd ๐’ข2) (ฮ”_eps_pair ๐’ข1 Q1 ๐’ข2 Q2)"
proof -
  from pair_at_langE assms obtain p q  q' r where
    wit: "(p, q) |โˆˆ| Q1" "p |โˆˆ| gta_der (fst ๐’ข1) s" "q |โˆˆ| gta_der (snd ๐’ข1) t"
    "(q', r) |โˆˆ| Q2" "q' |โˆˆ| gta_der (fst ๐’ข2) t" "r |โˆˆ| gta_der (snd ๐’ข2) u"
      by metis
  from wit(3, 5) have "(q, q') |โˆˆ| ฮ”ฮต (snd ๐’ข1) (fst ๐’ข2)"
    by (auto simp: ฮ”ฮต_def' gta_der_def intro!: exI[of _ "term_of_gterm t"])
  then have "(p, r) |โˆˆ| ฮ”_eps_pair ๐’ข1 Q1 ๐’ข2 Q2" using wit(1, 4)
    by (auto simp: ฮ”_eps_pair_def)
  then show ?thesis using wit(2, 6) unfolding pair_at_lang_def
    by auto
qed

lemma pair_comp_sound2:
  assumes "(s, u) โˆˆ  pair_at_lang (fst ๐’ข1, snd ๐’ข2) (ฮ”_eps_pair ๐’ข1 Q1 ๐’ข2 Q2)"
  shows "โˆƒ t. (s, t) โˆˆ pair_at_lang ๐’ข1 Q1 โˆง (t, u) โˆˆ pair_at_lang ๐’ข2 Q2"
  using assms unfolding pair_at_lang_def ฮ”_eps_pair_def
  by (auto simp: ฮ”ฮต_def' gta_der_def) (metis gterm_of_term_inv)

lemma pair_comp_sound:
  "pair_at_lang ๐’ข1 Q1 O pair_at_lang ๐’ข2 Q2 = pair_at_lang (fst ๐’ข1, snd ๐’ข2) (ฮ”_eps_pair ๐’ข1 Q1 ๐’ข2 Q2)"
  by (auto simp: pair_comp_sound1 pair_comp_sound2 relcomp.simps)

inductive_set ฮ”_Atrans_set :: "('q ร— 'q) fset โ‡’ ('q, 'f) ta โ‡’ ('q, 'f) ta โ‡’ ('q ร— 'q) set" for Q ๐’œ โ„ฌ where
  base [simp]: "(p, q) |โˆˆ| Q โŸน (p, q) โˆˆ ฮ”_Atrans_set Q ๐’œ โ„ฌ"
| step [intro]: "(p, q) โˆˆ ฮ”_Atrans_set Q ๐’œ โ„ฌ โŸน (q, r) |โˆˆ| ฮ”ฮต โ„ฌ ๐’œ โŸน
     (r, v) โˆˆ ฮ”_Atrans_set Q ๐’œ โ„ฌ โŸน (p, v) โˆˆ ฮ”_Atrans_set Q ๐’œ โ„ฌ"

lemma ฮ”_Atrans_set_states:
  "(p, q) โˆˆ ฮ”_Atrans_set Q ๐’œ โ„ฌ โŸน (p, q) โˆˆ fset ((fst |`| Q |โˆช| ๐’ฌ ๐’œ) |ร—| (snd |`| Q |โˆช| ๐’ฌ โ„ฌ))"
  by (induct rule: ฮ”_Atrans_set.induct) (auto simp: fimage_iff fBex_def simp flip: fmember.rep_eq)

lemma finite_ฮ”_Atrans_set: "finite (ฮ”_Atrans_set Q ๐’œ โ„ฌ)"
proof -
  have "ฮ”_Atrans_set Q ๐’œ โ„ฌ โІ fset ((fst |`| Q |โˆช| ๐’ฌ ๐’œ) |ร—| (snd |`| Q |โˆช| ๐’ฌ โ„ฌ))"
    using ฮ”_Atrans_set_states by auto
  from finite_subset[OF this] show ?thesis by simp
qed

context
includes fset.lifting
begin
lift_definition ฮ”_Atrans ::  "('q ร— 'q) fset โ‡’ ('q, 'f) ta โ‡’ ('q, 'f) ta โ‡’ ('q ร— 'q) fset" is ฮ”_Atrans_set
  by (simp add: finite_ฮ”_Atrans_set)

lemmas ฮ”_Atrans_base [simp] = ฮ”_Atrans_set.base [Transfer.transferred]
lemmas ฮ”_Atrans_step [intro] = ฮ”_Atrans_set.step [Transfer.transferred]
lemmas ฮ”_Atrans_cases = ฮ”_Atrans_set.cases[Transfer.transferred]
lemmas ฮ”_Atrans_induct [consumes 1, case_names base step] = ฮ”_Atrans_set.induct[Transfer.transferred]
end

"ฮ”_Atrans_gtt ๐’ข Q โ‰ก ฮ”_Atrans Q (fst ๐’ข) (snd ๐’ข)"">abbreviation "ฮ”_Atrans_gtt ๐’ข Q โ‰ก ฮ”_Atrans Q (fst ๐’ข) (snd ๐’ข)"

lemma pair_trancl_sound1:
  assumes "(s, t) โˆˆ (pair_at_lang ๐’ข Q)+"
  shows "โˆƒ q p. p |โˆˆ| gta_der (fst ๐’ข) s โˆง q |โˆˆ| gta_der (snd ๐’ข) t โˆง (p, q) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"
  using assms
proof (induct)
  case (step t v)
  obtain p q r r' where reach_t: "r |โˆˆ| gta_der (fst ๐’ข) t" "q |โˆˆ| gta_der (snd ๐’ข) t" and
    reach: "p |โˆˆ| gta_der (fst ๐’ข) s" "r' |โˆˆ| gta_der (snd ๐’ข) v" and
    st: "(p, q) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"  "(r, r') |โˆˆ| Q" using step(2, 3)
    by (auto simp: pair_at_lang_def)
  from reach_t have "(q, r) |โˆˆ| ฮ”ฮต (snd ๐’ข) (fst ๐’ข)"
    by (auto simp: ฮ”ฮต_def' gta_der_def intro: ground_term_of_gterm)
  then have "(p, r') |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q" using st by auto
  then show ?case using reach reach_t
    by (auto simp: pair_at_lang_def gta_der_def ฮ”ฮต_def' intro: ground_term_of_gterm)
qed (auto simp: pair_at_lang_def intro: ฮ”_Atrans_base)

lemma pair_trancl_sound2:
  assumes "(p, q) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"
    and "p |โˆˆ| gta_der (fst ๐’ข) s" "q |โˆˆ| gta_der (snd ๐’ข) t"
  shows "(s, t) โˆˆ (pair_at_lang ๐’ข Q)+" using assms
proof (induct arbitrary: s t rule:ฮ”_Atrans_induct)
  case (step p q r v)
  from step(2)[OF step(6)] step(5)[OF _ step(7)] step(3)
  show ?case by (auto simp: gta_der_def ฮ”ฮต_def' intro!: ground_term_of_gterm)
      (metis gterm_of_term_inv trancl_trans)
qed (auto simp: pair_at_lang_def)

lemma pair_trancl_sound:
  "(pair_at_lang ๐’ข Q)+ = pair_at_lang ๐’ข (ฮ”_Atrans_gtt ๐’ข Q)"
  by (auto simp: pair_trancl_sound2 dest: pair_trancl_sound1 elim: pair_at_langE intro: pair_at_langI)

"fst_pair_cl ๐’œ Q โ‰ก TA (rules ๐’œ) (eps ๐’œ |โˆช| (fId_on (๐’ฌ ๐’œ) |O| Q))"">abbreviation "fst_pair_cl ๐’œ Q โ‰ก TA (rules ๐’œ) (eps ๐’œ |โˆช| (fId_on (๐’ฌ ๐’œ) |O| Q))"
definition pair_at_to_agtt :: "('q, 'f) gtt โ‡’ ('q ร— 'q) fset โ‡’ ('q, 'f) gtt" where
  "pair_at_to_agtt ๐’ข Q = (fst_pair_cl (fst ๐’ข) Q , TA (rules (snd ๐’ข)) (eps (snd ๐’ข)))"

lemma fst_pair_cl_eps:
  assumes "(p, q) |โˆˆ| (eps (fst_pair_cl ๐’œ Q))|+|"
    and "๐’ฌ ๐’œ |โˆฉ| snd |`| Q = {||}"
  shows "(p, q) |โˆˆ| (eps ๐’œ)|+| โˆจ (โˆƒ r. (p = r โˆจ (p, r) |โˆˆ| (eps ๐’œ)|+|) โˆง (r, q) |โˆˆ| Q)" using assms
proof (induct rule: ftrancl_induct)
  case (Step p q r)
  then have y: "q |โˆˆ| ๐’ฌ ๐’œ" by (auto simp add: eps_trancl_statesD eps_statesD)
  have [simp]: "(p, q) |โˆˆ| Q โŸน q |โˆˆ| snd |`| Q" for p q by (auto simp: fimage_iff) force 
  then show ?case using Step y
    by auto (simp add: ftrancl_into_trancl)
qed auto

lemma fst_pair_cl_res_aux:
  assumes "๐’ฌ ๐’œ |โˆฉ| snd |`| Q = {||}"
    and "q |โˆˆ| ta_der (fst_pair_cl ๐’œ Q) (term_of_gterm t)"
  shows "โˆƒ p. p |โˆˆ| ta_der ๐’œ (term_of_gterm t) โˆง (q |โˆ‰| ๐’ฌ ๐’œ โŸถ (p, q) |โˆˆ| Q) โˆง (q |โˆˆ| ๐’ฌ ๐’œ โŸถ p = q)" using assms
proof (induct t arbitrary: q)
  case (GFun f ts)
  then obtain qs q' where rule: "TA_rule f qs q' |โˆˆ| rules ๐’œ" "length qs = length ts" and
    eps: "q' = q โˆจ (q', q) |โˆˆ| (eps (fst_pair_cl ๐’œ Q))|+|" and
    reach: "โˆ€ i < length ts. qs ! i |โˆˆ| ta_der (fst_pair_cl ๐’œ Q) (term_of_gterm (ts ! i))"
    by auto
  {fix i assume ass: "i < length ts" then have st: "qs ! i |โˆˆ| ๐’ฌ ๐’œ" using rule
      by (auto simp: rule_statesD)
    then have "qs ! i |โˆ‰| snd |`| Q" using GFun(2) by auto
    then have "qs ! i |โˆˆ| ta_der ๐’œ (term_of_gterm (ts ! i))" using reach st ass
      using fst_pair_cl_eps[OF _ GFun(2)] GFun(1)[OF nth_mem[OF ass] GFun(2), of "qs ! i"]
      by blast} note IH = this
  show ?case
  proof (cases "q' = q")
    case True
    then show ?thesis using rule reach IH
      by (auto dest: rule_statesD intro!: exI[of _ q'] exI[of _ qs])
  next
    case False note nt_eq = this
    then have eps: "(q', q) |โˆˆ| (eps (fst_pair_cl ๐’œ Q))|+|" using eps by simp
    from fst_pair_cl_eps[OF this assms(1)] show ?thesis
      using False rule IH
    proof (cases "q |โˆ‰| ๐’ฌ ๐’œ")
      case True
      from fst_pair_cl_eps[OF eps assms(1)] obtain r where
         "q' = r โˆจ (q', r) |โˆˆ| (eps ๐’œ)|+|" "(r, q) |โˆˆ| Q" using True
        by (auto simp: eps_trancl_statesD)
      then show ?thesis using nt_eq rule IH True
        by (auto simp: fimage_iff eps_trancl_statesD)
    next
      case False
      from fst_pair_cl_eps[OF eps assms(1)] False assms(1)
      have "(q', q) |โˆˆ| (eps ๐’œ)|+|"
        by (auto simp: fimage_iff) (metis fempty_iff fimage_eqI finterI snd_conv)+
      then show ?thesis using IH rule
        by (intro exI[of _ q]) (auto simp: eps_trancl_statesD)
    qed
  qed
qed

lemma restr_distjoing:
  assumes "Q |โІ| ๐’ฌ ๐’œ |ร—| ๐’ฌ ๐”…"
    and "๐’ฌ ๐’œ |โˆฉ| ๐’ฌ ๐”… = {||}"
  shows "๐’ฌ ๐’œ |โˆฉ| snd |`| Q = {||}"
  using assms by auto

lemma pair_at_agtt_conv:
  assumes "Q |โІ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)" and "๐’ฌ (fst ๐’ข) |โˆฉ| ๐’ฌ (snd ๐’ข) = {||}"
  shows "pair_at_lang ๐’ข Q = agtt_lang (pair_at_to_agtt ๐’ข Q)" (is "?LS = ?RS")
proof
  let ?TA = "fst_pair_cl (fst ๐’ข) Q"
  {fix s t assume ls: "(s, t) โˆˆ ?LS"
    then obtain q p where w: "(q, p) |โˆˆ| Q" "q |โˆˆ| gta_der (fst ๐’ข) s" "p |โˆˆ| gta_der (snd ๐’ข) t"
      by (auto elim: pair_at_langE)
    from w(2) have "q |โˆˆ| gta_der ?TA s" "q |โˆˆ| ๐’ฌ (fst ๐’ข)"
      using ta_der_mono'[of "fst ๐’ข" ?TA "term_of_gterm s"]
      by (auto simp add: fin_mono ta_subset_def gta_der_def in_mono)
    then have "(s, t) โˆˆ ?RS" using w(1, 3)
      by (auto simp: pair_at_to_agtt_def agtt_lang_def gta_der_def ta_der_eps intro!: exI[of _ p])
         (metis fId_onI frelcompI funionI2 ta.sel(2) ta_der_eps)}
  then show "?LS โІ ?RS" by auto
next
  {fix s t assume ls: "(s, t) โˆˆ ?RS"
    then obtain q where w: "q |โˆˆ| ta_der (fst_pair_cl (fst ๐’ข) Q) (term_of_gterm s)"
      "q |โˆˆ| ta_der (snd ๐’ข) (term_of_gterm t)"
      by (auto simp: agtt_lang_def pair_at_to_agtt_def gta_der_def)
    from w(2) have "q |โˆˆ| ๐’ฌ (snd ๐’ข)" "q |โˆ‰| ๐’ฌ (fst ๐’ข)" using assms(2)
      by auto
    from fst_pair_cl_res_aux[OF restr_distjoing[OF assms] w(1)] this w(2)
    have "(s, t) โˆˆ ?LS" by (auto simp: agtt_lang_def pair_at_to_agtt_def gta_der_def intro: pair_at_langI)}
  then show "?RS โІ ?LS" by auto
qed

definition pair_at_to_agtt' where
  "pair_at_to_agtt' ๐’ข Q = (let ๐’œ = fmap_states_ta Inl (fst ๐’ข) in
    let โ„ฌ = fmap_states_ta Inr (snd ๐’ข) in
    let Q' = Q |โˆฉ| (๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)) in
    pair_at_to_agtt (๐’œ, โ„ฌ) (map_prod Inl Inr |`| Q'))"

lemma pair_at_agtt_cost:
  "pair_at_lang ๐’ข Q = agtt_lang (pair_at_to_agtt' ๐’ข Q)"
proof -
  let ?G = "(fmap_states_ta CInl (fst ๐’ข), fmap_states_ta CInr (snd ๐’ข))"
  let ?Q = "(Q |โˆฉ| (๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)))"
  let ?Q' = "map_prod CInl CInr |`| ?Q"
  have *: "pair_at_lang ๐’ข Q = pair_at_lang ๐’ข ?Q"
    using pair_at_lang_restr_states by blast
  have "pair_at_lang ๐’ข ?Q = pair_at_lang (map_prod (fmap_states_ta CInl) (fmap_states_ta CInr) ๐’ข) (map_prod CInl CInr |`| ?Q)"
    by (intro pair_at_lang_fun_states[where ?๐’ข = ๐’ข and ?Q = ?Q and ?f = CInl and ?g = CInr])
       (auto simp: finj_CInl_CInr)
  then have **:"pair_at_lang ๐’ข ?Q = pair_at_lang ?G ?Q'" by (simp add: map_prod_simp')
  have "pair_at_lang ?G ?Q' = agtt_lang (pair_at_to_agtt ?G ?Q')"
    by (intro pair_at_agtt_conv[where ?๐’ข = ?G]) auto
  then show ?thesis unfolding * ** pair_at_to_agtt'_def Let_def
    by simp
qed

lemma ฮ”_Atrans_states_stable:
  assumes "Q |โІ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)"
  shows "ฮ”_Atrans_gtt ๐’ข Q |โІ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)"
proof
  fix s assume ass: "s |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"
  then obtain t u where s: "s = (t, u)" by (cases s) blast
  show "s |โˆˆ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)" using ass assms unfolding s
    by (induct rule: ฮ”_Atrans_induct) auto
qed

lemma ฮ”_Atrans_map_prod:
  assumes "finj_on f (๐’ฌ (fst ๐’ข))" and "finj_on g (๐’ฌ (snd ๐’ข))"
    and "Q |โІ| ๐’ฌ (fst ๐’ข) |ร—| ๐’ฌ (snd ๐’ข)"
  shows "map_prod f g |`| (ฮ”_Atrans_gtt ๐’ข Q) = ฮ”_Atrans_gtt (map_prod (fmap_states_ta f) (fmap_states_ta g) ๐’ข) (map_prod f g |`| Q)"
    (is "?LS = ?RS")
proof -
  {fix p q assume "(p, q) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"
    then have "(f p, g q) |โˆˆ| ?RS" using assms
    proof (induct rule: ฮ”_Atrans_induct)
      case (step p q r v)
      from step(3, 6, 7) have "(g q, f r) |โˆˆ| ฮ”ฮต (fmap_states_ta g (snd ๐’ข)) (fmap_states_ta f (fst ๐’ข))"
        by (auto simp: ฮ”ฮต_def' intro!: ground_term_of_gterm)
           (metis ground_term_of_gterm ground_term_to_gtermD ta_der_to_fmap_states_der)
      then show ?case using step by auto
    qed (auto simp add: fmap_prod_fimageI)}
  moreover
  {fix p q assume "(p, q) |โˆˆ| ?RS"
    then have "(p, q) |โˆˆ| ?LS" using assms
    proof (induct rule: ฮ”_Atrans_induct)
      case (step p q r v)
      let ?f = "the_finv_into (๐’ฌ (fst ๐’ข)) f" let ?g = "the_finv_into (๐’ฌ (snd ๐’ข)) g"
      have sub: "ฮ”ฮต (snd ๐’ข) (fst ๐’ข) |โІ| ๐’ฌ (snd ๐’ข) |ร—| ๐’ฌ (fst ๐’ข)"
        using ฮ”ฮต_statesD(1, 2) by fastforce
      have s_e: "(?f p, ?g q) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q" "(?f r, ?g v) |โˆˆ| ฮ”_Atrans_gtt ๐’ข Q"
        using step assms(1, 2) fsubsetD[OF ฮ”_Atrans_states_stable[OF assms(3)]]
        using finj_on_eq_iff[OF assms(1)] finj_on_eq_iff
        using the_finv_into_f_f[OF assms(1)] the_finv_into_f_f[OF assms(2)]
        by auto
      from step(3) have "(?g q, ?f r) |โˆˆ| ฮ”ฮต (snd ๐’ข) (fst ๐’ข)"
        using step(6-) sub
        using ta_der_fmap_states_conv[OF assms(1)] ta_der_fmap_states_conv[OF assms(2)]
        using the_finv_into_f_f[OF assms(1)] the_finv_into_f_f[OF assms(2)]
        by (auto simp: ฮ”ฮต_fmember fimage_iff fBex_def)
           (metis ground_term_of_gterm ground_term_to_gtermD ta_der_fmap_states_inv)
      then have "(q, r) |โˆˆ| map_prod g f |`| ฮ”ฮต (snd ๐’ข) (fst ๐’ข)" using step
        using the_finv_into_f_f[OF assms(1)] the_finv_into_f_f[OF assms(2)] sub
        by auto (smt ฮ”ฮต_statesD(1, 2) f_the_finv_into_f fmap_prod_fimageI fmap_states)
      then show ?case using s_e assms(1, 2) s_e
        using fsubsetD[OF sub]
        using fsubsetD[OF ฮ”_Atrans_states_stable[OF assms(3)]]
        using ฮ”_Atrans_step[of "?f p" "?g q" Q "fst ๐’ข" "snd ๐’ข" "?f r" "?g v"]
        using the_finv_into_f_f[OF assms(1)] the_finv_into_f_f[OF assms(2)]
        by  (auto simp: fimage_iff fBex_def)
            (smt Pair_inject prod_fun_fimageE step.hyps(2) step.hyps(5) step.prems(3))
    qed auto}
  ultimately show ?thesis by auto
qed

โ€• โ€นSection: Pair Automaton is closed under Determinizationโ€บ

"Q_pow Q ๐’ฎ_1 ๐’ฎ_2 =">definition "Q_pow Q ๐’ฎ1 ๐’ฎ2 =
  {|(X, Y) | X Y p q. X |โˆˆ| fPow ๐’ฎ1 โˆง Y |โˆˆ| fPow ๐’ฎ2 โˆง p |โˆˆ| X โˆง q |โˆˆ| Y โˆง (p, q) |โˆˆ| Q|}"

lemma Q_pow_fmember:
  "(X, Y) |โˆˆ| Q_pow Q ๐’ฎ1 ๐’ฎ2 โŸท (โˆƒ p q. X |โˆˆ| fPow ๐’ฎ1 โˆง Y |โˆˆ| fPow ๐’ฎ2 โˆง p |โˆˆ| X โˆง q |โˆˆ| Y โˆง (p, q) |โˆˆ| Q)"
proof -
  have "{(X, Y) | X Y p q. X |โˆˆ| fPow ๐’ฎ1 โˆง Y |โˆˆ| fPow ๐’ฎ2 โˆง p |โˆˆ| X โˆง q |โˆˆ| Y โˆง (p, q) |โˆˆ| Q} โІ fset (fPow ๐’ฎ1 |ร—| fPow ๐’ฎ2)"
    by (auto simp flip: fmember.rep_eq)
  from finite_subset[OF this] show ?thesis unfolding Q_pow_def
    by auto
qed

lemma pair_automaton_det_lang_sound_complete:
  "pair_at_lang ๐’ข Q = pair_at_lang (map_both ps_ta ๐’ข) (Q_pow Q (๐’ฌ (fst ๐’ข)) (๐’ฌ (snd ๐’ข)))" (is "?LS = ?RS")
proof -
  {fix s t assume "(s, t) โˆˆ ?LS"
    then obtain  p q where
      res : "p |โˆˆ| ta_der (fst ๐’ข) (term_of_gterm s)"
      "q |โˆˆ| ta_der (snd ๐’ข) (term_of_gterm t)" "(p, q) |โˆˆ| Q"
      by (auto simp: pair_at_lang_def gta_der_def)
    from ps_rules_complete[OF this(1)] ps_rules_complete[OF this(2)] this(3)
    have "(s, t) โˆˆ ?RS" using fPow_iff ps_ta_states
      by (auto simp:  pair_at_lang_def gta_der_def Q_pow_fmember)
         force}
  moreover
  {fix s t assume "(s, t) โˆˆ ?RS" then have "(s, t) โˆˆ ?LS"
      using ps_rules_sound
      by (auto simp: pair_at_lang_def gta_der_def ps_ta_def Let_def Q_pow_def) blast}
  ultimately show ?thesis by auto
qed

lemma pair_automaton_complement_sound_complete:
  assumes "completely_defined_on ๐’œ โ„ฑ" and "completely_defined_on โ„ฌ โ„ฑ"
    and "ta_det ๐’œ" and "ta_det โ„ฌ"
  shows "pair_at_lang (๐’œ, โ„ฌ) (๐’ฌ ๐’œ |ร—| ๐’ฌ โ„ฌ |-| Q) = gterms (fset โ„ฑ) ร— gterms (fset โ„ฑ) - pair_at_lang (๐’œ, โ„ฌ) Q"
  using assms unfolding completely_defined_on_def pair_at_lang_def
  apply (auto simp: gta_der_def)
  apply (metis ta_detE)
  apply fastforce
  done
(*
lemma pair_automaton_lang_on:
  fixes ๐’ข defines "โ„ฑ1 โ‰ก ta_sig (fst ๐’ข)" and "โ„ฑ2 โ‰ก ta_sig (snd ๐’ข)"
  shows "pair_at_lang ๐’ข Q โІ gterms (fset โ„ฑ1) ร— gterms (fset โ„ฑ2)"
  using assms funas_term_of_gterm_conv
  by (auto simp: pair_at_lang_def gta_der_def) fastforce+
*)
end