Theory NBTA_Combine

section ‹Nondeterministic Büchi Transition Automata Combinations›

theory NBTA_Combine
imports NBTA NGBTA
begin

  global_interpretation degeneralization: automaton_degeneralization_run
    ngbta ngbta.alphabet ngbta.initial ngbta.transition ngbta.accepting "λ P w r p. gen infs P (p ## r ||| w ||| r)"
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    id "λ ((p, k), a, (q, l)). ((p, a, q), k)"
    defines degeneralize = degeneralization.degeneralize
  proof
    fix w :: "'a stream"
    fix r :: "'b stream"
    fix cs p k
    let ?f = "λ ((p, k), a, (q, l)). ((p, a, q), k)"
    let ?s = "sscan (count cs ∘ id) (p ## r ||| w ||| r) k"
    have "infs (degen cs ∘ ?f) ((p, k) ## (r ||| ?s) ||| w ||| (r ||| ?s)) ⟷
      infs (degen cs) (smap ?f ((p, k) ## (r ||| ?s) ||| w ||| (r ||| ?s)))"
      by (simp add: comp_def)
    also have "smap ?f ((p, k) ## (r ||| ?s) ||| w ||| (r ||| ?s)) = (p ## r ||| w ||| r) ||| k ## ?s"
      by (coinduction arbitrary: p k r w) (auto simp: eq_scons simp flip: szip_unfold sscan_scons)
    also have "… = (p ## r ||| w ||| r) ||| k ## sscan (count cs) (p ## r ||| w ||| r) k" by simp
    also have "infs (degen cs) … = gen infs cs (p ## r ||| w ||| r)" using degen_infs by this
    finally show "infs (degen cs ∘ ?f) ((p, k) ## (r ||| ?s) ||| w ||| (r ||| ?s)) ⟷
      gen infs cs (p ## r ||| w ||| r)" by this
  qed

  lemmas degeneralize_language[simp] = degeneralization.degeneralize_language[folded NBTA.language_def]
  lemmas degeneralize_nodes_finite[iff] = degeneralization.degeneralize_nodes_finite[folded NBTA.nodes_def]

  global_interpretation intersection: automaton_intersection_run
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    ngbta ngbta.alphabet ngbta.initial ngbta.transition ngbta.accepting "λ P w r p. gen infs P (p ## r ||| w ||| r)"
    "λ c1 c2. [c1 ∘ (λ ((p1, p2), a, (q1, q2)). (p1, a, q1)), c2 ∘ (λ ((p1, p2), a, (q1, q2)). (p2, a, q2))]"
    defines intersect' = intersection.product
  proof
    fix w :: "'a stream"
    fix u :: "'b stream"
    fix v :: "'c stream"
    fix c1 c2 p q
    let ?tfst = "λ ((p1, p2), a, (q1, q2)). (p1, a, q1)"
    let ?tsnd = "λ ((p1, p2), a, (q1, q2)). (p2, a, q2)"
    have "gen infs [c1 ∘ ?tfst, c2 ∘ ?tsnd] ((p, q) ## (u ||| v) ||| w ||| u ||| v) ⟷
      infs c1 (smap ?tfst ((p, q) ## (u ||| v) ||| w ||| u ||| v)) ∧
      infs c2 (smap ?tsnd ((p, q) ## (u ||| v) ||| w ||| u ||| v))"
      unfolding gen_def by (simp add: comp_def)
    also have "smap ?tfst ((p, q) ## (u ||| v) ||| w ||| u ||| v) = p ## u ||| w ||| u"
      by (coinduction arbitrary: p q u v w) (auto simp flip: szip_unfold, metis stream.collapse)
    also have "smap ?tsnd ((p, q) ## (u ||| v) ||| w ||| u ||| v) = q ## v ||| w ||| v"
      by (coinduction arbitrary: p q u v w) (auto simp flip: szip_unfold, metis stream.collapse)
    finally show "gen infs [c1 ∘ ?tfst, c2 ∘ ?tsnd] ((p, q) ## (u ||| v) ||| w ||| u ||| v) ⟷
      infs c1 (p ## u ||| w ||| u) ∧ infs c2 (q ## v ||| w ||| v)" by this
  qed

  lemmas intersect'_language[simp] = intersection.product_language[folded NGBTA.language_def]
  lemmas intersect'_nodes_finite[intro] = intersection.product_nodes_finite[folded NGBTA.nodes_def]

  global_interpretation union: automaton_union_run
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    nbta nbta.alphabet nbta.initial nbta.transition nbta.accepting "λ P w r p. infs P (p ## r ||| w ||| r)"
    "λ c1 c2 m. case m of (Inl p, a, Inl q) ⇒ c1 (p, a, q) | (Inr p, a, Inr q) ⇒ c2 (p, a, q)"
    defines union = union.sum
    by (unfold_locales) (auto simp add: szip_smap_fold comp_def case_prod_unfold simp flip: stream.map)

  lemmas union_language = union.sum_language
  lemmas union_nodes_finite = union.sum_nodes_finite

  abbreviation intersect where "intersect A B ≡ degeneralize (intersect' A B)"

  lemma intersect_language[simp]: "NBTA.language (intersect A B) = NBTA.language A ∩ NBTA.language B"
    by simp
  lemma intersect_nodes_finite[intro]:
    assumes "finite (NBTA.nodes A)" "finite (NBTA.nodes B)"
    shows "finite (NBTA.nodes (intersect A B))"
    using intersect'_nodes_finite assms by simp

end