Theory Complementation

section ‹Complementation›

theory Complementation
imports
  "Transition_Systems_and_Automata.Maps"
  "Ranking"
begin

  subsection ‹Level Rankings and Complementation States›

  type_synonym 'state lr = "'state  nat"

  definition lr_succ :: "('label, 'state) nba  'label  'state lr  'state lr set" where
    "lr_succ A a f  {g.
      dom g =  (transition A a ` dom f) 
      ( p  dom f.  q  transition A a p. the (g q)  the (f p)) 
      ( q  dom g. accepting A q  even (the (g q)))}"

  type_synonym 'state st = "'state set"

  definition st_succ :: "('label, 'state) nba  'label  'state lr  'state st  'state st" where
    "st_succ A a g P  {q  if P = {} then dom g else  (transition A a ` P). even (the (g q))}"

  type_synonym 'state cs = "'state lr × 'state st"

  definition complement_succ :: "('label, 'state) nba  'label  'state cs  'state cs set" where
    "complement_succ A a  λ (f, P). {(g, st_succ A a g P) |g. g  lr_succ A a f}"

  definition complement :: "('label, 'state) nba  ('label, 'state cs) nba" where
    "complement A  nba
      (alphabet A)
      ({const (Some (2 * card (nodes A))) |` initial A} × {{}})
      (complement_succ A)
      (λ (f, P). P = {})"

  lemma dom_nodes:
    assumes "fP  nodes (complement A)"
    shows "dom (fst fP)  nodes A"
    using assms unfolding complement_def complement_succ_def lr_succ_def by (induct) (auto, blast)
  lemma ran_nodes:
    assumes "fP  nodes (complement A)"
    shows "ran (fst fP)  {0 .. 2 * card (nodes A)}"
  using assms
  proof induct
    case (initial fP)
    show ?case
      using initial unfolding complement_def by (auto) (metis eq_refl option.inject ran_restrictD)
  next
    case (execute fP agQ)
    obtain f P where 1: "fP = (f, P)" by force
    have 2: "ran f  {0 .. 2 * card (nodes A)}" using execute(2) unfolding 1 by auto
    obtain a g Q where 3: "agQ = (a, (g, Q))" using prod_cases3 by this
    have 4: "p  dom f  q  transition A a p  the (g q)  the (f p)" for p q
      using execute(3)
      unfolding 1 3 complement_def nba.simps complement_succ_def lr_succ_def
      by simp
    have 8: "dom g = ((transition A a) ` (dom f))"
      using execute(3)
      unfolding 1 3 complement_def nba.simps complement_succ_def lr_succ_def
      by simp
    show ?case
    unfolding 1 3 ran_def
    proof safe
      fix q k
      assume 5: "fst (snd (a, (g, Q))) q = Some k"
      have 6: "q  dom g" using 5 by auto
      obtain p where 7: "p  dom f" "q  transition A a p" using 6 unfolding 8 by auto
      have "k = the (g q)" using 5 by auto
      also have "  the (f p)" using 4 7 by this
      also have "  2 * card (nodes A)" using 2 7(1) by (simp add: domD ranI subset_eq)
      finally show "k  {0 .. 2 * card (nodes A)}" by auto
    qed
  qed
  lemma states_nodes:
    assumes "fP  nodes (complement A)"
    shows "snd fP  nodes A"
  using assms
  proof induct
    case (initial fP)
    show ?case using initial unfolding complement_def by auto
  next
    case (execute fP agQ)
    obtain f P where 1: "fP = (f, P)" by force
    have 2: "P  nodes A" using execute(2) unfolding 1 by auto
    obtain a g Q where 3: "agQ = (a, (g, Q))" using prod_cases3 by this
    have 11: "a  alphabet A" using execute(3) unfolding 3 complement_def by auto
    have 10: "(g, Q)  nodes (complement A)" using execute(1, 3) unfolding 1 3 by auto
    have 4: "dom g  nodes A" using dom_nodes[OF 10] by simp
    have 5: " (transition A a ` P)  nodes A" using 2 11 by auto
    have 6: "Q  nodes A"
      using execute(3)
      unfolding 1 3 complement_def nba.simps complement_succ_def st_succ_def
      using 4 5
      by (auto split: if_splits)
    show ?case using 6 unfolding 3 by auto
  qed

  theorem complement_finite:
    assumes "finite (nodes A)"
    shows "finite (nodes (complement A))"
  proof -
    let ?lrs = "{f. dom f  nodes A  ran f  {0 .. 2 * card (nodes A)}}"
    have 1: "finite ?lrs" using finite_set_of_finite_maps' assms by auto
    let ?states = "Pow (nodes A)"
    have 2: "finite ?states" using assms by simp
    have "nodes (complement A)  ?lrs × ?states" by (force dest: dom_nodes ran_nodes states_nodes)
    also have "finite " using 1 2 by simp
    finally show ?thesis by this
  qed

  lemma complement_trace_snth:
    assumes "run (complement A) (w ||| r) p"
    defines "m  p ## trace (w ||| r) p"
    obtains
      "fst (m !! Suc k)  lr_succ A (w !! k) (fst (m !! k))"
      "snd (m !! Suc k) = st_succ A (w !! k) (fst (m !! Suc k)) (snd (m !! k))"
  proof
    have 1: "r !! k  transition (complement A) (w !! k) (m !! k)" using nba.run_snth assms by force
    show "fst (m !! Suc k)  lr_succ A (w !! k) (fst (m !! k))"
      using assms(2) 1 unfolding complement_def complement_succ_def nba.trace_alt_def by auto
    show "snd (m !! Suc k) = st_succ A (w !! k) (fst (m !! Suc k)) (snd (m !! k))"
      using assms(2) 1 unfolding complement_def complement_succ_def nba.trace_alt_def by auto
  qed

  subsection ‹Word in Complement Language Implies Ranking›

  lemma complement_ranking:
    assumes "w  language (complement A)"
    obtains f
    where "ranking A w f"
  proof -
    obtain r p where 1:
      "run (complement A) (w ||| r) p"
      "p  initial (complement A)"
      "infs (accepting (complement A)) (p ## r)"
      using assms by rule
    let ?m = "p ## r"
    obtain 100:
      "fst (?m !! Suc k)  lr_succ A (w !! k) (fst (?m !! k))"
      "snd (?m !! Suc k) = st_succ A (w !! k) (fst (?m !! Suc k)) (snd (?m !! k))"
      for k using complement_trace_snth 1(1) unfolding nba.trace_alt_def szip_smap_snd by metis
    define f where "f  λ (k, q). the (fst (?m !! k) q)"
    define P where "P k  snd (?m !! k)" for k
    have 2: "snd v  dom (fst (?m !! fst v))" if "v  gunodes A w" for v
    using that
    proof induct
      case (initial v)
      then show ?case using 1(2) unfolding complement_def by auto
    next
      case (execute v u)
      have "snd u   (transition A (w !! fst v) ` dom (fst (?m !! fst v)))"
        using execute(2, 3) by auto
      also have " = dom (fst (?m !! Suc (fst v)))"
        using 100 unfolding lr_succ_def by simp
      also have "Suc (fst v) = fst u" using execute(3) by auto
      finally show ?case by this
    qed
    have 3: "f u  f v" if 10: "v  gunodes A w" and 11: "u  gusuccessors A w v" for u v
    proof -
      have 15: "snd u  transition A (w !! fst v) (snd v)" using 11 by auto
      have 16: "snd v  dom (fst (?m !! fst v))" using 2 10 by this
      have "f u = the (fst (?m !! fst u) (snd u))" unfolding f_def by (simp add: case_prod_beta)
      also have "fst u = Suc (fst v)" using 11 by auto
      also have "the (fst (?m !! ) (snd u))  the (fst (?m !! fst v) (snd v))"
        using 100 15 16 unfolding lr_succ_def by auto
      also have " = f v" unfolding f_def by (simp add: case_prod_beta)
      finally show "f u  f v" by this
    qed
    have 4: " l  k. P l = {}" for k
    proof -
      have 15: "infs (λ (k, P). P = {}) ?m" using 1(3) unfolding complement_def by auto
      obtain l where 17: "l  k" "snd (?m !! l) = {}" using 15 unfolding infs_snth by force
      have 19: "P l = {}" unfolding P_def using 17 by auto
      show ?thesis using 19 17(1) by auto
    qed
    show ?thesis
    proof (rule that, unfold ranking_def, intro conjI ballI impI allI)
      fix v
      assume "v  gunodes A w"
      then show "f v  2 * card (nodes A)"
      proof induct
        case (initial v)
        then show ?case using 1(2) unfolding complement_def f_def by auto
      next
        case (execute v u)
        have "f u  f v" using 3[OF execute(1)] execute(3) by simp
        also have "  2 * card (nodes A)" using execute(2) by this
        finally show ?case by this
      qed
    next
      fix v u
      assume 10: "v  gunodes A w"
      assume 11: "u  gusuccessors A w v"
      show "f u  f v" using 3 10 11 by this
    next
      fix v
      assume 10: "v  gunodes A w"
      assume 11: "gaccepting A v"
      show "even (f v)"
      using 10
      proof cases
        case (initial)
        then show ?thesis using 1(2) unfolding complement_def f_def by auto
      next
        case (execute u)
        have 12: "snd v  dom (fst (?m !! fst v))" using execute graph.nodes.execute 2 by blast
        have 12: "snd v  dom (fst (?m !! Suc (fst u)))" using 12 execute(2) by auto
        have 13: "accepting A (snd v)" using 11 by auto
        have "f v = the (fst (?m !! fst v) (snd v))" unfolding f_def by (simp add: case_prod_beta)
        also have "fst v = Suc (fst u)" using execute(2) by auto
        also have "even (the (fst (?m !! Suc (fst u)) (snd v)))"
          using 100 12 13 unfolding lr_succ_def by simp
        finally show ?thesis by this
      qed
    next
      fix v s k
      assume 10: "v  gunodes A w"
      assume 11: "gurun A w s v"
      assume 12: "smap f (gtrace s v) = sconst k"
      show "odd k"
      proof
        assume 13: "even k"
        obtain t u where 14: "u  ginitial A" "gupath A w t u" "v = gtarget t u" using 10 by auto
        obtain l where 15: "l  length t" "P l = {}" using 4 by auto
        have 30: "gurun A w (t @- s) u" using 11 14 by auto
        have 21: "fst (gtarget (stake (Suc l) (t @- s)) u) = Suc l" for l
          unfolding sscan_snth[symmetric] using 30 14(1) by (auto elim!: grun_elim)
        have 17: "snd (gtarget (stake (Suc l + i) (t @- s)) u)  P (Suc l + i)" for i
        proof (induct i)
          case (0)
          have 20: "gtarget (stake (Suc l) (t @- s)) u  gunodes A w"
            using 14 11 by (force simp add: 15(1) le_SucI graph.run_stake stake_shift)
          have "snd (gtarget (stake (Suc l) (t @- s)) u) 
            dom (fst (?m !! fst (gtarget (stake (Suc l) (t @- s)) u)))"
            using 2[OF 20] by this
          also have "fst (gtarget (stake (Suc l) (t @- s)) u) = Suc l" using 21 by this
          finally have 22: "snd (gtarget (stake (Suc l) (t @- s)) u)  dom (fst (?m !! Suc l))" by this
          have "gtarget (stake (Suc l) (t @- s)) u = gtrace (t @- s) u !! l" unfolding sscan_snth by rule
          also have " = gtrace s v !! (l - length t)" using 15(1) by simp
          also have "f  = smap f (gtrace s v) !! (l - length t)" by simp
          also have "smap f (gtrace s v) = sconst k" unfolding 12 by rule
          also have "sconst k !! (l - length t) = k" by simp
          finally have 23: "even (f (gtarget (stake (Suc l) (t @- s)) u))" using 13 by simp
          have "snd (gtarget (stake (Suc l) (t @- s)) u) 
            {p  dom (fst (?m !! Suc l)). even (f (Suc l, p))}"
            using 21 22 23 by (metis (mono_tags, lifting) mem_Collect_eq prod.collapse)
          also have " = st_succ A (w !! l) (fst (?m !! Suc l)) (P l)"
            unfolding 15(2) st_succ_def f_def by simp
          also have " = P (Suc l)" using 100(2) unfolding P_def by rule
          finally show ?case by auto
        next
          case (Suc i)
          have 20: "P (Suc l + i)  {}" using Suc by auto
          have 21: "fst (gtarget (stake (Suc l + Suc i) (t @- s)) u) = Suc l + Suc i"
            using 21 by (simp add: stake_shift)
          have "gtarget (stake (Suc l + Suc i) (t @- s)) u = gtrace (t @- s) u !! (l + Suc i)"
            unfolding sscan_snth by simp
          also have "  gusuccessors A w (gtarget (stake (Suc (l + i)) (t @- s)) u)"
            using graph.run_snth[OF 30, of "l + Suc i"] by simp
          finally have 220: "snd (gtarget (stake (Suc (Suc l + i)) (t @- s)) u) 
              transition A (w !! (Suc l + i)) (snd (gtarget (stake (Suc (l + i)) (t @- s)) u))"
            using 21 by auto
          have 22: "snd (gtarget (stake (Suc l + Suc i) (t @- s)) u) 
             (transition A (w !! (Suc l + i)) ` P (Suc l + i))" using 220 Suc by auto
          have "gtarget (stake (Suc l + Suc i) (t @- s)) u = gtrace (t @- s) u !! (l + Suc i)"
            unfolding sscan_snth by simp
          also have " = gtrace s v !! (l + Suc i - length t)" using 15(1)
            by (metis add.commute shift_snth_ge sscan_const trans_le_add2)
          also have "f  = smap f (gtrace s v) !! (l + Suc i - length t)" by simp
          also have "smap f (gtrace s v) = sconst k" unfolding 12 by rule
          also have "sconst k !! (l + Suc i - length t) = k" by simp
          finally have 23: "even (f (gtarget (stake (Suc l + Suc i) (t @- s)) u))" using 13 by auto
          have "snd (gtarget (stake (Suc l + Suc i) (t @- s)) u) 
            {p   (transition A (w !! (Suc l + i)) ` P (Suc l + i)). even (f (Suc (Suc l + i), p))}"
            using 21 22 23 by (metis (mono_tags) add_Suc_right mem_Collect_eq prod.collapse)
          also have " = st_succ A (w !! (Suc l + i)) (fst (?m !! Suc (Suc l + i))) (P (Suc l + i))"
            unfolding st_succ_def f_def using 20 by simp
          also have " = P (Suc (Suc l + i))" unfolding 100(2)[folded P_def] by rule
          also have " = P (Suc l + Suc i)" by simp
          finally show ?case by this
        qed
        obtain l' where 16: "l'  Suc l" "P l' = {}" using 4 by auto
        show "False" using 16 17 using nat_le_iff_add by auto
      qed
    qed
  qed

  subsection ‹Ranking Implies Word in Complement Language›

  definition reach where
    "reach A w i  {target r p |r p. path A r p  p  initial A  map fst r = stake i w}"

  lemma reach_0[simp]: "reach A w 0 = initial A" unfolding reach_def by auto
  lemma reach_Suc_empty:
    assumes "w !! n  alphabet A"
    shows "reach A w (Suc n) = {}"
  proof safe
    fix q
    assume 1: "q  reach A w (Suc n)"
    obtain r p where 2: "q = target r p" "path A r p" "p  initial A" "map fst r = stake (Suc n) w"
      using 1 unfolding reach_def by blast
    have 3: "path A (take n r @ drop n r) p" using 2(2) by simp
    have 4: "map fst r = stake n w @ [w !! n]" using 2(4) stake_Suc by auto
    have 5: "map snd r = take n (map snd r) @ [q]" using 2(1, 4) 4
      by (metis One_nat_def Suc_inject Suc_neq_Zero Suc_pred append.right_neutral
        append_eq_conv_conj drop_map id_take_nth_drop last_ConsR last_conv_nth length_0_conv
        length_map length_stake lessI nba.target_alt_def nba.states_alt_def zero_less_Suc)
    have 6: "drop n r = [(w !! n, q)]" using 4 5
      by (metis append_eq_conv_conj append_is_Nil_conv append_take_drop_id drop_map
        length_greater_0_conv length_stake stake_cycle_le stake_invert_Nil
        take_map zip_Cons_Cons zip_map_fst_snd)
    show "q  {}" using assms 3 unfolding 6 by auto
  qed
  lemma reach_Suc_succ:
    assumes "w !! n  alphabet A"
    shows "reach A w (Suc n) =  (transition A (w !! n) ` reach A w n)"
  proof safe
    fix q
    assume 1: "q  reach A w (Suc n)"
    obtain r p where 2: "q = target r p" "path A r p" "p  initial A" "map fst r = stake (Suc n) w"
      using 1 unfolding reach_def by blast
    have 3: "path A (take n r @ drop n r) p" using 2(2) by simp
    have 4: "map fst r = stake n w @ [w !! n]" using 2(4) stake_Suc by auto
    have 5: "map snd r = take n (map snd r) @ [q]" using 2(1, 4) 4
      by (metis One_nat_def Suc_inject Suc_neq_Zero Suc_pred append.right_neutral
        append_eq_conv_conj drop_map id_take_nth_drop last_ConsR last_conv_nth length_0_conv
        length_map length_stake lessI nba.target_alt_def nba.states_alt_def zero_less_Suc)
    have 6: "drop n r = [(w !! n, q)]" using 4 5
      by (metis append_eq_conv_conj append_is_Nil_conv append_take_drop_id drop_map
        length_greater_0_conv length_stake stake_cycle_le stake_invert_Nil
        take_map zip_Cons_Cons zip_map_fst_snd)
    show "q  ((transition A (w !! n) ` (reach A w n)))"
    unfolding reach_def
    proof (intro UN_I CollectI exI conjI)
      show "target (take n r) p = target (take n r) p" by rule
      show "path A (take n r) p" using 3 by blast
      show "p  initial A" using 2(3) by this
      show "map fst (take n r) = stake n w" using 2 by (metis length_stake lessI nat.distinct(1)
        stake_cycle_le stake_invert_Nil take_map take_stake)
      show "q  transition A (w !! n) (target (take n r) p)" using 3 unfolding 6 by auto
    qed
  next
    fix p q
    assume 1: "p  reach A w n" "q  transition A (w !! n) p"
    obtain r x where 2: "p = target r x" "path A r x" "x  initial A" "map fst r = stake n w"
      using 1(1) unfolding reach_def by blast
    show "q  reach A w (Suc n)"
    unfolding reach_def
    proof (intro CollectI exI conjI)
      show "q = target (r @ [(w !! n, q)]) x" using 1 2 by auto
      show "path A (r @ [(w !! n, q)]) x" using assms 1(2) 2(1, 2) by auto
      show "x  initial A" using 2(3) by this
      show "map fst (r @ [(w !! n, q)]) = stake (Suc n) w" using 1 2
        by (metis eq_fst_iff list.simps(8) list.simps(9) map_append stake_Suc)
    qed
  qed
  lemma reach_Suc[simp]: "reach A w (Suc n) = (if w !! n  alphabet A
    then  (transition A (w !! n) ` reach A w n) else {})"
    using reach_Suc_empty reach_Suc_succ by metis
  lemma reach_nodes: "reach A w i  nodes A" by (induct i) (auto)
  lemma reach_gunodes: "{i} × reach A w i  gunodes A w"
    by (induct i) (auto intro: graph.nodes.execute)

  lemma ranking_complement:
    assumes "finite (nodes A)" "w  streams (alphabet A)" "ranking A w f"
    shows "w  language (complement A)"
  proof -
    define f' where "f'  λ (k, p). if k = 0 then 2 * card (nodes A) else f (k, p)"
    have 0: "ranking A w f'"
    unfolding ranking_def
    proof (intro conjI ballI impI allI)
      show " v. v  gunodes A w  f' v  2 * card (nodes A)"
        using assms(3) unfolding ranking_def f'_def by auto
      show " v u. v  gunodes A w  u  gusuccessors A w v  f' u  f' v"
        using assms(3) unfolding ranking_def f'_def by fastforce
      show " v. v  gunodes A w  gaccepting A v  even (f' v)"
        using assms(3) unfolding ranking_def f'_def by auto
    next
      have 1: "v  gunodes A w  gurun A w r v  smap f (gtrace r v) = sconst k  odd k"
        for v r k using assms(3) unfolding ranking_def by meson
      fix v r k
      assume 2: "v  gunodes A w" "gurun A w r v" "smap f' (gtrace r v) = sconst k"
      have 20: "shd r  gureachable A w v" using 2
        by (auto) (metis graph.reachable.reflexive graph.reachable_trace gtrace_alt_def subsetD shd_sset)
      obtain 3:
        "shd r  gunodes A w"
        "gurun A w (stl r) (shd r)"
        "smap f' (gtrace (stl r) (shd r)) = sconst k"
        using 2 20 by (metis (no_types, lifting) eq_id_iff graph.nodes_trans graph.run_scons_elim
          siterate.simps(2) sscan.simps(2) stream.collapse stream.map_sel(2))
      have 4: "k  0" if "(k, p)  sset r" for k p
      proof -
        obtain ra ka pa where 1: "r = fromN (Suc ka) ||| ra" "v = (ka, pa)"
          using grun_elim[OF 2(2)] by this
        have 2: "k  sset (fromN (Suc ka))" using 1(1) that
          by (metis image_eqI prod.sel(1) szip_smap_fst stream.set_map)
        show ?thesis using 2 by simp
      qed
      have 5: "smap f' (gtrace (stl r) (shd r)) = smap f (gtrace (stl r) (shd r))"
      proof (rule stream.map_cong)
        show "gtrace (stl r) (shd r) = gtrace (stl r) (shd r)" by rule
      next
        fix z
        assume 1: "z  sset (gtrace (stl r) (shd r))"
        have 2: "fst z  0" using 4 1 by (metis gtrace_alt_def prod.collapse stl_sset)
        show "f' z = f z" using 2 unfolding f'_def by (auto simp: case_prod_beta)
      qed
      show "odd k" using 1 3 5 by simp
    qed

    define g where "g i p  if p  reach A w i then Some (f' (i, p)) else None" for i p
    have g_dom[simp]: "dom (g i) = reach A w i" for i
      unfolding g_def by (auto) (metis option.simps(3))
    have g_0[simp]: "g 0 = const (Some (2 * card (nodes A))) |` initial A"
      unfolding g_def f'_def by auto
    have g_Suc[simp]: "g (Suc n)  lr_succ A (w !! n) (g n)" for n
    unfolding lr_succ_def
    proof (intro CollectI conjI ballI impI)
      show "dom (g (Suc n)) =  (transition A (w !! n) ` dom (g n))" using snth_in assms(2) by auto
    next
      fix p q
      assume 100: "p  dom (g n)" "q  transition A (w !! n) p"
      have 101: "q  reach A w (Suc n)" using snth_in assms(2) 100 by auto
      have 102: "(n, p)  gunodes A w" using 100(1) reach_gunodes g_dom by blast
      have 103: "(Suc n, q)  gusuccessors A w (n, p)" using snth_in assms(2) 102 100(2) by auto
      have 104: "p  reach A w n" using 100(1) by simp
      have "g (Suc n) q = Some (f' (Suc n, q))" using 101 unfolding g_def by simp
      also have "the  = f' (Suc n, q)" by simp
      also have "  f' (n, p)" using 0 unfolding ranking_def using 102 103 by simp
      also have " = the (Some (f' (n, p)))" by simp
      also have "Some (f' (n, p)) = g n p" using 104 unfolding g_def by simp
      finally show "the (g (Suc n) q)  the (g n p)" by this
    next
      fix p
      assume 100: "p  dom (g (Suc n))" "accepting A p"
      have 101: "p  reach A w (Suc n)" using 100(1) by simp
      have 102: "(Suc n, p)  gunodes A w" using 101 reach_gunodes by blast
      have 103: "gaccepting A (Suc n, p)" using 100(2) by simp
      have "the (g (Suc n) p) = f' (Suc n, p)" using 101 unfolding g_def by simp
      also have "even " using 0 unfolding ranking_def using 102 103 by auto
      finally show "even (the (g (Suc n) p))" by this
    qed

    define P where "P  rec_nat {} (λ n. st_succ A (w !! n) (g (Suc n)))"
    have P_0[simp]: "P 0 = {}" unfolding P_def by simp
    have P_Suc[simp]: "P (Suc n) = st_succ A (w !! n) (g (Suc n)) (P n)" for n
      unfolding P_def by simp
    have P_reach: "P n  reach A w n" for n
      using snth_in assms(2) by (induct n) (auto simp add: st_succ_def)
    have "P n  reach A w n" for n using P_reach by auto
    also have " n  nodes A" for n using reach_nodes by this
    also have "finite (nodes A)" using assms(1) by this
    finally have P_finite: "finite (P n)" for n by this

    define s where "s  smap g nats ||| smap P nats"

    show ?thesis
    proof
      show "run (complement A) (w ||| stl s) (shd s)"
      proof (intro nba.snth_run conjI, simp_all del: stake.simps stake_szip)
        fix k
        show "w !! k  alphabet (complement A)" using snth_in assms(2) unfolding complement_def by auto
        have "stl s !! k = s !! Suc k" by simp
        also have "  complement_succ A (w !! k) (s !! k)"
          unfolding complement_succ_def s_def using P_Suc by simp
        also have " = complement_succ A (w !! k) (target (stake k (w ||| stl s)) (shd s))"
          unfolding sscan_scons_snth[symmetric] nba.trace_alt_def by simp
        also have " = transition (complement A) (w !! k) (target (stake k (w ||| stl s)) (shd s))"
          unfolding complement_def nba.sel by rule
        finally show "stl s !! k 
          transition (complement A) (w !! k) (target (stake k (w ||| stl s)) (shd s))" by this
      qed
      show "shd s  initial (complement A)" unfolding complement_def s_def using P_0 by simp
      show "infs (accepting (complement A)) (shd s ## stl s)"
      proof -
        have 10: " n.  k  n. P k = {}"
        proof (rule ccontr)
          assume 20: "¬ ( n.  k  n. P k = {})"
          obtain k where 22: "P (k + n)  {}" for n using 20 using le_add1 by blast
          define m where "m n S  {p   (transition A (w !! n) ` S). even (the (g (Suc n) p))}" for n S
          define R where "R i n S  rec_nat S (λ i. m (n + i)) i" for i n S
          have R_0[simp]: "R 0 n = id" for n unfolding R_def by auto
          have R_Suc[simp]: "R (Suc i) n = m (n + i)  R i n" for i n unfolding R_def by auto
          have R_Suc': "R (Suc i) n = R i (Suc n)  m n" for i n unfolding R_Suc by (induct i) (auto)
          have R_reach: "R i n S  reach A w (n + i)" if "S  reach A w n" for i n S
            using snth_in assms(2) that m_def by (induct i) (auto)
          have P_R: "P (k + i) = R i k (P k)" for i
            using 22 by (induct i) (auto simp add: case_prod_beta' m_def st_succ_def)

          have 50: "R i n S = ( p  S. R i n {p})" for i n S
            by (induct i) (auto simp add: m_def prod.case_eq_if)
          have 51: "R (i + j) n S = {}" if "R i n S = {}" for i j n S
            using that by (induct j) (auto simp add: m_def prod.case_eq_if)
          have 52: "R j n S = {}" if "i  j" "R i n S = {}" for i j n S
            using 51 by (metis le_add_diff_inverse that(1) that(2))

          have 1: " p  S.  i. R i n {p}  {}"
            if assms: "finite S" " i. R i n S  {}" for n S
          proof (rule ccontr)
            assume 1: "¬ ( p  S.  i. R i n {p}  {})"
            obtain f where 3: " p. p  S  R (f p) n {p} = {}" using 1 by metis
            have 4: "R (Sup (f ` S)) n {p} = {}" if "p  S" for p
            proof (rule 52)
              show "f p  Sup (f ` S)" using assms(1) that by (auto intro: le_cSup_finite)
              show "R (f p) n {p} = {}" using 3 that by this
            qed
            have "R (Sup (f ` S)) n S = ( p  S. R (Sup (f ` S)) n {p})" using 50 by this
            also have " = {}" using 4 by simp
            finally have 5: "R (Sup (f ` S)) n S = {}" by this
            show "False" using that(2) 5 by auto
          qed
          have 2: " i. R i (k + 0) (P k)  {}" using 22 P_R by simp
          obtain p where 3: "p  P k" " i. R i k {p}  {}" using 1[OF P_finite 2] by auto

          define Q where "Q n p  ( i. R i (k + n) {p}  {})  p  P (k + n)" for n p
          have 5: " q  transition A (w !! (k + n)) p. Q (Suc n) q" if "Q n p" for n p
          proof -
            have 11: "p  P (k + n)" " i. R i (k + n) {p}  {}" using that unfolding Q_def by auto
            have 12: "R (Suc i) (k + n) {p}  {}" for i using 11(2) by this
            have 13: "R i (k + Suc n) (m (k + n) {p})  {}" for i using 12 unfolding R_Suc' by simp
            have "{p}  P (k + n)" using 11(1) by auto
            also have "  reach A w (k + n)" using P_reach by this
            finally have "R 1 (k + n) {p}  reach A w (k + n + 1)" using R_reach by blast
            also have "  nodes A" using reach_nodes by this
            also have "finite (nodes A)" using assms(1) by this
            finally have 14: "finite (m (k + n) {p})" by simp
            obtain q where 14: "q  m (k + n) {p}" " i. R i (k + Suc n) {q}  {}"
              using 1[OF 14 13] by auto
            show ?thesis
            unfolding Q_def prod.case
            proof (intro bexI conjI allI)
              show " i. R i (k + Suc n) {q}  {}" using 14(2) by this
              show "q  P (k + Suc n)"
                using 14(1) 11(1) 22 unfolding m_def by (auto simp add: st_succ_def)
              show "q  transition A (w !! (k + n)) p" using 14(1) unfolding m_def by simp
            qed
          qed
          obtain r where 23:
            "run A r p" " i. Q i ((p ## trace r p) !! i)" " i. fst (r !! i) = w !! (k + i)"
          proof (rule nba.invariant_run_index[of Q 0 p A "λ n p a. fst a = w !! (k + n)"])
            show "Q 0 p" unfolding Q_def using 3 by auto
            show " a. (fst a  alphabet A  snd a  transition A (fst a) p) 
              Q (Suc n) (snd a)  fst a = w !! (k + n)" if "Q n p" for n p
              using snth_in assms(2) 5 that by fastforce
          qed auto
          have 20: "smap fst r = sdrop k w" using 23(3) by (intro eqI_snth) (simp add: case_prod_beta)
          have 21: "(p ## smap snd r) !! i  P (k + i)" for i
            using 23(2) unfolding Q_def unfolding nba.trace_alt_def by simp
          obtain r where 23: "run A (sdrop k w ||| stl r) (shd r)" " i. r !! i  P (k + i)"
            using 20 21 23(1) by (metis stream.sel(1) stream.sel(2) szip_smap)
          let ?v = "(k, shd r)"
          let ?r = "fromN (Suc k) ||| stl r"
          have "shd r = r !! 0" by simp
          also have "  P k" using 23(2)[of 0] by simp
          also have "  reach A w k" using P_reach by this
          finally have 24: "?v  gunodes A w" using reach_gunodes by blast
          have 25: "gurun A w ?r ?v" using run_grun 23(1) by this
          obtain l where 26: "Ball (sset (smap f' (gtrace (sdrop l ?r) (gtarget (stake l ?r) ?v)))) odd"
            using ranking_stuck_odd 0 24 25 by this
          have 27: "f' (Suc (k + l), r !! Suc l) =
            shd (smap f' (gtrace (sdrop l ?r) (gtarget (stake l ?r) ?v)))" by (simp add: algebra_simps)
          also have "  sset (smap f' (gtrace (sdrop l ?r) (gtarget (stake l ?r) ?v)))"
            using shd_sset by this
          finally have 28: "odd (f' (Suc (k + l), r !! Suc l))" using 26 by auto
          have "r !! Suc l  P (Suc (k + l))" using 23(2) by (metis add_Suc_right)
          also have " = {p   (transition A (w !! (k + l)) ` P (k + l)).
            even (the (g (Suc (k + l)) p))}" using 23(2) by (auto simp: st_succ_def)
          also have "  {p. even (the (g (Suc (k + l)) p))}" by auto
          finally have 29: "even (the (g (Suc (k + l)) (r !! Suc l)))" by auto
          have 30: "r !! Suc l  reach A w (Suc (k + l))"
            using 23(2) P_reach by (metis add_Suc_right subsetCE)
          have 31: "even (f' (Suc (k + l), r !! Suc l))" using 29 30 unfolding g_def by simp
          show "False" using 28 31 by simp
        qed
        have 11: "infs (λ k. P k = {}) nats" using 10 unfolding infs_snth by simp
        have "infs (λ S. S = {}) (smap snd (smap g nats ||| smap P nats))"
          using 11 by (simp add: comp_def)
        then have "infs (λ x. snd x = {}) (smap g nats ||| smap P nats)"
          by (simp add: comp_def del: szip_smap_snd)
        then have "infs (λ (f, P). P = {}) (smap g nats ||| smap P nats)" 
          by (simp add: case_prod_beta')
        then have "infs (λ (f, P). P = {}) (stl (smap g nats ||| smap P nats))" by blast
        then have "infs (λ (f, P). P = {}) (smap snd (w ||| stl (smap g nats ||| smap P nats)))" by simp
        then have "infs (λ (f, P). P = {}) (stl s)" unfolding s_def by simp
        then show ?thesis unfolding complement_def by auto
      qed
    qed
  qed

  subsection ‹Correctness Theorem›

  theorem complement_language:
    assumes "finite (nodes A)"
    shows "language (complement A) = streams (alphabet A) - language A"
  proof (safe del: notI)
    have 1: "alphabet (complement A) = alphabet A" unfolding complement_def nba.sel by rule
    show "w  streams (alphabet A)" if "w  language (complement A)" for w
      using nba.language_alphabet that 1 by force
    show "w  language A" if "w  language (complement A)" for w
      using complement_ranking ranking_language that by metis
    show "w  language (complement A)" if "w  streams (alphabet A)" "w  language A" for w
      using language_ranking ranking_complement assms that by blast
  qed

end