Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/VYDRA_MDL/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 29.4.2026 mit Größe 99 kB image not shown  

Quelle  Monitor.thy

  Sprache: Isabelle
 

theory Monitor
  imports MDL Temporal
begin

type_synonym ('h, 't) time = "('h × 't) option"

datatype (dead 'a, dead 't :: timestamp, dead 'h) vydra_aux =
    VYDRA_None
  | VYDRA_Bool bool 'h
  | VYDRA_Atom 'a 'h
  | VYDRA_Neg "('a, 't, 'h) vydra_aux"
  | VYDRA_Bin "bool ==> bool ==> bool" "('a, 't, 'h) vydra_aux" "('a, 't, 'h) vydra_aux"
  | VYDRA_Prev "'t I" "('a, 't, 'h) vydra_aux" 'h "('t × bool) option"
  | VYDRA_Next "'t I" "('a, 't, 'h) vydra_aux" 'h "'t option"
  | VYDRA_Since "'t I" "('a, 't, 'h) vydra_aux" "('a, 't, 'h) vydra_aux" "('h, 't) time" nat nat "nat option" "'t option"
  | VYDRA_Until "'t I" "('h, 't) time" "('a, 't, 'h) vydra_aux" "('a, 't, 'h) vydra_aux" "('h, 't) time" nat "('t × bool × bool) option"
  | VYDRA_MatchP "'t I" "transition iarray" nat
    "(bool iarray, nat set, 't, ('h, 't) time, ('a, 't, 'h) vydra_aux list) window"
  | VYDRA_MatchF "'t I" "transition iarray" nat
    "(bool iarray, nat set, 't, ('h, 't) time, ('a, 't, 'h) vydra_aux list) window"

type_synonym ('a, 't, 'h) vydra = "nat × ('a, 't, 'h) vydra_aux"

fun msize_vydra :: "nat ==> ('a, 't :: timestamp, 'h) vydra_aux ==> nat" where
  "msize_vydra n VYDRA_None = 0"
"msize_vydra n (VYDRA_Bool b e) = 0"
"msize_vydra n (VYDRA_Atom a e) = 0"
"msize_vydra (Suc n) (VYDRA_Bin f v1 v2) = msize_vydra n v1 + msize_vydra n v2 + 1"
"msize_vydra (Suc n) (VYDRA_Neg v) = msize_vydra n v + 1"
"msize_vydra (Suc n) (VYDRA_Prev I v e tb) = msize_vydra n v + 1"
"msize_vydra (Suc n) (VYDRA_Next I v e to) = msize_vydra n v + 1"
"msize_vydra (Suc n) (VYDRA_Since I vphi vpsi e cphi cpsi cppsi tppsi) = msize_vydra n vphi + msize_vydra n vpsi + 1"
"msize_vydra (Suc n) (VYDRA_Until I e vphi vpsi epsi c zo) = msize_vydra n vphi + msize_vydra n vpsi + 1"
"msize_vydra (Suc n) (VYDRA_MatchP I transs qf w) = size_list (msize_vydra n) (w_si w) + size_list (msize_vydra n) (w_sj w) + 1"
"msize_vydra (Suc n) (VYDRA_MatchF I transs qf w) = size_list (msize_vydra n) (w_si w) + size_list (msize_vydra n) (w_sj w) + 1"
"msize_vydra _ _ = 0"

fun next_vydra :: "('a, 't :: timestamp, 'h) vydra_aux ==> nat" where
  "next_vydra (VYDRA_Next I v e None) = 1"
"next_vydra _ = 0"

context
  fixes init_hd :: "'h"
    and run_hd :: "'h ==> ('h × ('t :: timestamp × 'a set)) option"
begin

definition t0 :: "('h, 't) time" where
  "t0 = (case run_hd init_hd of None ==> None | Some (e', (t, X)) ==> Some (e', t))"

fun run_t :: "('h, 't) time ==> (('h, 't) time × 't) option" where
  "run_t None = None"
"run_t (Some (e, t)) = (case run_hd e of None ==> Some (None, t)
  | Some (e', (t', X)) ==> Some (Some (e', t'), t))"

fun read_t :: "('h, 't) time ==> 't option" where
  "read_t None = None"
"read_t (Some (e, t)) = Some t"

lemma run_t_read: "run_t x = Some (x', t) ==> read_t x = Some t"
  by (cases x) (auto split: option.splits)

lemma read_t_run: "read_t x = Some t ==> x'. run_t x = Some (x', t)"
  by (cases x) (auto split: option.splits)

lemma reach_event_t: "reaches_on run_hd e vs e'' ==> run_hd e = Some (e', (t, X)) ==>
  run_hd e'' = Some (e''', (t', X')) ==>
  reaches_on run_t (Some (e', t)) (map fst vs) (Some (e''', t'))"
proof (induction e vs e'' arbitrary: t' X' e''' rule: reaches_on_rev_induct)
  case (2 s s' v vs s'')
  obtain v_t v_X where v_def: "v = (v_t, v_X)"
    by (cases v) auto
  have run_t_s'': "run_t (Some (s'', v_t)) = Some (Some (e''', t'), v_t)"
    by (auto simp: 2(5))
  show ?case
    using reaches_on_app[OF 2(3)[OF 2(42(2)[unfolded v_def]] run_t_s'']
    by (auto simp: v_def)
qed (auto intro: reaches_on.intros)

lemma reach_event_t0_t:
  assumes "reaches_on run_hd init_hd vs e''" "run_hd e'' = Some (e''', (t', X'))"
  shows "reaches_on run_t t0 (map fst vs) (Some (e''', t'))"
proof -
  have t0_not_None: "t0 None"
    apply (rule reaches_on.cases[OF assms(1)])
    using assms(2)
    by (auto simp: t0_def split: option.splits prod.splits)
  then show ?thesis
    using reach_event_t[OF assms(1) _ assms(2)]
    by (auto simp: t0_def split: option.splits)
qed

lemma reaches_on_run_hd_t:
  assumes "reaches_on run_hd init_hd vs e"
  shows "x. reaches_on run_t t0 (map fst vs) x"
proof (cases vs rule: rev_cases)
  case (snoc ys y)
  show ?thesis
    using assms
    apply (cases y)
    apply (auto simp: snoc dest!: reaches_on_split_last)
    apply (meson reaches_on_app[OF reach_event_t0_t] read_t.simps(2) read_t_run)
    done
qed (auto intro: reaches_on.intros)

definition "run_subs run = (λvs. let vs' = map run vs in
  (if (x set vs'. Option.is_none x) then None
   else Some (map (fst the) vs', iarray_of_list (map (snd snd the) vs'))))"

lemma run_subs_lD: "run_subs run vs = Some (vs', bs) ==>
  length vs' = length vs IArray.length bs = length vs"
  by (auto simp: run_subs_def Let_def iarray_of_list_def split: option.splits if_splits)

lemma run_subs_vD: "run_subs run vs = Some (vs', bs) ==> j < length vs ==>
  vj' tj bj. run (vs ! j) = Some (vj', (tj, bj)) vs' ! j = vj' IArray.sub bs j = bj"
  apply (cases "run (vs ! j)")
   apply (auto simp: Option.is_none_def run_subs_def Let_def iarray_of_list_def
      split: option.splits if_splits)
  by (metis image_eqI nth_mem)

fun msize_fmla :: "('a, 'b :: timestamp) formula ==> nat"
  and msize_regex :: "('a, 'b) regex ==> nat" where
  "msize_fmla (Bool b) = 0"
"msize_fmla (Atom a) = 0"
"msize_fmla (Neg phi) = Suc (msize_fmla phi)"
"msize_fmla (Bin f phi psi) = Suc (msize_fmla phi + msize_fmla psi)"
"msize_fmla (Prev I phi) = Suc (msize_fmla phi)"
"msize_fmla (Next I phi) = Suc (msize_fmla phi)"
"msize_fmla (Since phi I psi) = Suc (max (msize_fmla phi) (msize_fmla psi))"
"msize_fmla (Until phi I psi) = Suc (max (msize_fmla phi) (msize_fmla psi))"
"msize_fmla (MatchP I r) = Suc (msize_regex r)"
"msize_fmla (MatchF I r) = Suc (msize_regex r)"
"msize_regex (Lookahead phi) = msize_fmla phi"
"msize_regex (Symbol phi) = msize_fmla phi"
"msize_regex (Plus r s) = max (msize_regex r) (msize_regex s)"
"msize_regex (Times r s) = max (msize_regex r) (msize_regex s)"
"msize_regex (Star r) = msize_regex r"

lemma collect_subfmlas_msize: "x set (collect_subfmlas r []) ==>
  msize_fmla x msize_regex r"
proof (induction r)
  case (Lookahead phi)
  then show ?case
    by (auto split: if_splits)
next
  case (Symbol phi)
  then show ?case
    by (auto split: if_splits)
next
  case (Plus r1 r2)
  then show ?case
    by (auto simp: collect_subfmlas_set[of r2 "collect_subfmlas r1 []"])
next
  case (Times r1 r2)
  then show ?case
    by (auto simp: collect_subfmlas_set[of r2 "collect_subfmlas r1 []"])
next
  case (Star r)
  then show ?case
    by fastforce
qed

definition "until_ready I t c zo = (case (c, zo) of (Suc _, Some (t', b1, b2)) ==> (b2 memL t t' I) ¬b1 | _ ==> False)"

definition "while_since_cond I t = (λ(vpsi, e, cpsi :: nat, cppsi, tppsi). cpsi > 0 memL (the (read_t e)) t I)"
definition "while_since_body run =
  (λ(vpsi, e, cpsi :: nat, cppsi, tppsi).
    case run vpsi of Some (vpsi', (t', b')) ==>
      Some (vpsi', fst (the (run_t e)), cpsi - 1, if b' then Some cpsi else cppsi, if b' then Some t' else tppsi)
      | _ ==> None
    )"

definition "while_until_cond I t = (λ(vphi, vpsi, epsi, c, zo). ¬until_ready I t c zo (case read_t epsi of Some t' ==> memR t t' I | None ==> False))"
definition "while_until_body run =
  (λ(vphi, vpsi, epsi, c, zo). case run_t epsi of Some (epsi', t') ==>
    (case run vphi of Some (vphi', (_, b1)) ==>
      (case run vpsi of Some (vpsi', (_, b2)) ==> Some (vphi', vpsi', epsi', Suc c, Some (t', b1, b2))
      | _ ==> None)
    | _ ==> None))"

function (sequential) run :: "nat ==> ('a, 't, 'h) vydra_aux ==> (('a, 't, 'h) vydra_aux × ('t × bool)) option" where
  "run n (VYDRA_None) = None"
"run n (VYDRA_Bool b e) = (case run_hd e of None ==> None
    | Some (e', (t, _)) ==> Some (VYDRA_Bool b e', (t, b)))"
"run n (VYDRA_Atom a e) = (case run_hd e of None ==> None
    | Some (e', (t, X)) ==> Some (VYDRA_Atom a e', (t, a X)))"
"run (Suc n) (VYDRA_Neg v) = (case run n v of None ==> None
    | Some (v', (t, b)) ==> Some (VYDRA_Neg v', (t, ¬b)))"
"run (Suc n) (VYDRA_Bin f vl vr) = (case run n vl of None ==> None
    | Some (vl', (t, bl)) ==> (case run n vr of None ==> None
    | Some (vr', (_, br)) ==> Some (VYDRA_Bin f vl' vr', (t, f bl br))))"
"run (Suc n) (VYDRA_Prev I v e tb) = (case run_hd e of Some (e', (t, _)) ==>
        (let β = (case tb of Some (t', b') ==> b' mem t' t I | None ==> False) in
        case run n v of Some (v', _, b') ==> Some (VYDRA_Prev I v' e' (Some (t, b')), (t, β))
        | None ==> Some (VYDRA_None, (t, β)))
    | None ==> None)"
"run (Suc n) (VYDRA_Next I v e to) = (case run_hd e of Some (e', (t, _)) ==>
    (case to of None ==>
      (case run n v of Some (v', _, _) ==> run (Suc n) (VYDRA_Next I v' e' (Some t))
      | None ==> None)
    | Some t' ==>
      (case run n v of Some (v', _, b) ==> Some (VYDRA_Next I v' e' (Some t), (t', b mem t' t I))
      | None ==> if mem t' t I then None else Some (VYDRA_None, (t', False))))
    | None ==> None)"
"run (Suc n) (VYDRA_Since I vphi vpsi e cphi cpsi cppsi tppsi) = (case run n vphi of
    Some (vphi', (t, b1)) ==>
      let cphi = (if b1 then Suc cphi else 0) in
      let cpsi = Suc cpsi in
      let cppsi = map_option Suc cppsi in
      (case while_break (while_since_cond I t) (while_since_body (run n)) (vpsi, e, cpsi, cppsi, tppsi) of Some (vpsi', e', cpsi', cppsi', tppsi') ==>
        (let β = (case cppsi' of Some k ==> k - 1 cphi memR (the tppsi') t I | _ ==> False) in
         Some (VYDRA_Since I vphi' vpsi' e' cphi cpsi' cppsi' tppsi', (t, β)))
      | _ ==> None)
    | _ ==> None)"
"run (Suc n) (VYDRA_Until I e vphi vpsi epsi c zo) = (case run_t e of Some (e', t) ==>
      (case while_break (while_until_cond I t) (while_until_body (run n)) (vphi, vpsi, epsi, c, zo) of Some (vphi', vpsi', epsi', c', zo') ==>
        if c' = 0 then None else
        (case zo' of Some (t', b1, b2) ==>
          (if b2 memL t t' I then Some (VYDRA_Until I e' vphi' vpsi' epsi' (c' - 1) zo', (t, True))
          else if ¬b1 then Some (VYDRA_Until I e' vphi' vpsi' epsi' (c' - 1) zo', (t, False))
          else (case read_t epsi' of Some t' ==> Some (VYDRA_Until I e' vphi' vpsi' epsi' (c' - 1) zo', (t, False)) | _ ==> None))
        | _ ==> None)
      | _ ==> None)
    | _ ==> None)"
"run (Suc n) (VYDRA_MatchP I transs qf w) =
    (case eval_matchP (init_args ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (run_t, read_t) (run_subs (run n))) I w of None ==> None
    | Some ((t, b), w') ==> Some (VYDRA_MatchP I transs qf w', (t, b)))"
"run (Suc n) (VYDRA_MatchF I transs qf w) =
    (case eval_matchF (init_args ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (run_t, read_t) (run_subs (run n))) I w of None ==> None
    | Some ((t, b), w') ==> Some (VYDRA_MatchF I transs qf w', (t, b)))"
"run _ _ = undefined"
  by pat_completeness auto
termination
  by (relation "(λp. size (fst p)) <*mlex*> (λp. next_vydra (snd p)) <*mlex*> (λp. msize_vydra (fst p) (snd p)) <*mlex*> {}") (auto simp: mlex_prod_def)

lemma wf_since: "wf {(t, s). while_since_cond I tt s Some t = while_since_body (run n) s}"
proof -
  let ?X = "{(t, s). while_since_cond I tt s Some t = while_since_body (run n) s}"
  have sub: "?X measure (λ(vpsi, e, cpsi, cppsi, tppsi). cpsi)"
    by (auto simp: while_since_cond_def while_since_body_def Let_def split: option.splits)
  then show ?thesis
    using wf_subset[OF wf_measure]
    by auto
qed

definition run_vydra :: "('a, 't, 'h) vydra ==> (('a, 't, 'h) vydra × ('t × bool)) option" where
  "run_vydra v = (case v of (n, w) ==> map_option (apfst (Pair n)) (run n w))"

fun sub :: "nat ==> ('a, 't) formula ==> ('a, 't, 'h) vydra_aux" where
  "sub n (Bool b) = VYDRA_Bool b init_hd"
"sub n (Atom a) = VYDRA_Atom a init_hd"
"sub (Suc n) (Neg phi) = VYDRA_Neg (sub n phi)"
"sub (Suc n) (Bin f phi psi) = VYDRA_Bin f (sub n phi) (sub n psi)"
"sub (Suc n) (Prev I phi) = VYDRA_Prev I (sub n phi) init_hd None"
"sub (Suc n) (Next I phi) = VYDRA_Next I (sub n phi) init_hd None"
"sub (Suc n) (Since phi I psi) = VYDRA_Since I (sub n phi) (sub n psi) t0 0 0 None None"
"sub (Suc n) (Until phi I psi) = VYDRA_Until I t0 (sub n phi) (sub n psi) t0 0 None"
"sub (Suc n) (MatchP I r) = (let qf = state_cnt r;
    transs = iarray_of_list (build_nfa_impl r (0, qf, [])) in
    VYDRA_MatchP I transs qf (init_window (init_args
      ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (run_t, read_t) (run_subs (run n)))
      t0 (map (sub n) (collect_subfmlas r []))))"
"sub (Suc n) (MatchF I r) = (let qf = state_cnt r;
    transs = iarray_of_list (build_nfa_impl r (0, qf, [])) in
    VYDRA_MatchF I transs qf (init_window (init_args
      ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (run_t, read_t) (run_subs (run n)))
      t0 (map (sub n) (collect_subfmlas r []))))"
"sub _ _ = undefined"

definition init_vydra :: "('a, 't) formula ==> ('a, 't, 'h) vydra" where
  "init_vydra φ = (let n = msize_fmla φ in (n, sub n φ))"

end

locale VYDRA_MDL = MDL σ
  for σ :: "('a, 't :: timestamp) trace" +
  fixes init_hd :: "'h"
    and run_hd :: "'h ==> ('h × ('t × 'a set)) option"
  assumes run_hd_sound: "reaches run_hd init_hd n s ==> run_hd s = Some (s', (t, X)) ==> (t, X) = (τ σ n, Γ σ n)"
begin

lemma reaches_on_run_hd: "reaches_on run_hd init_hd es s ==> run_hd s = Some (s', (t, X)) ==> t = τ σ (length es) X = Γ σ (length es)"
  using run_hd_sound
  by (auto dest: reaches_on_n)

abbreviation "ru_t run_t run_hd"
abbreviation "l_t0 t0 init_hd run_hd"
abbreviation "ru run run_hd"
abbreviation "su sub init_hd run_hd"

lemma ru_t_event: "reaches_on ru_t t ts t' ==> t = l_t0 ==> ru_t t' = Some (t'', x) ==>
  rho e tt. t' = Some (e, tt) reaches_on run_hd init_hd rho e length rho = Suc (length ts)
  x = τ σ (length ts)"
proof (induction t ts t' arbitrary: t'' x rule: reaches_on_rev_induct)
  case (1 s)
  show ?case
    using 1 reaches_on_run_hd[OF reaches_on.intros(1)]
    by (auto simp: t0_def split: option.splits intro!: reaches_on.intros)
next
  case (2 s s' v vs s'')
  obtain rho e tt where rho_def: "s' = Some (e, tt)" "reaches_on run_hd init_hd rho e"
    "length rho = Suc (length vs)"
    using 2(3)[OF 2(4,2)]
    by auto
  then show ?case
    using 2(2,5) reaches_on_app[OF rho_def(2)] reaches_on_run_hd[OF rho_def(2)]
    by (fastforce split: option.splits)
qed

lemma ru_t_tau: "reaches_on ru_t l_t0 ts t' ==> ru_t t' = Some (t'', x) ==> x = τ σ (length ts)"
  using ru_t_event
  by fastforce

lemma ru_t_Some_tau:
  assumes "reaches_on ru_t l_t0 ts (Some (e, t))"
  shows "t = τ σ (length ts)"
proof -
  obtain z where z_def: "ru_t (Some (e, t)) = Some (z, t)"
    by (cases "run_hd e") auto
  show ?thesis
    by (rule ru_t_tau[OF assms z_def])
qed

lemma ru_t_tau_in:
  assumes "reaches_on ru_t l_t0 ts t" "j < length ts"
  shows "ts ! j = τ σ j"
proof -
  obtain t' where t'_def"reaches_on ru_t l_t0 (take j ts) t'" "reaches_on ru_t t' (drop j ts) t"
    using reaches_on_split'[OF assms(1), where ?i=j] assms(2)
    by auto
  have drop: "drop j ts = ts ! j # tl (drop j ts)"
    using assms(2)
    by (cases "drop j ts") (auto simp add: nth_via_drop)
  obtain t'' where t''_def"ru_t t' = Some (t'', ts ! j)"
    using t'_def(2) assms(2) drop
    by (auto elim: reaches_on.cases)
  show ?thesis
    using ru_t_event[OF t'_def(1) refl t''_def] assms(2)
    by auto
qed

lemmas run_hd_tau_in = ru_t_tau_in[OF reach_event_t0_t, simplified]

fun last_before :: "(nat ==> bool) ==> nat ==> nat option" where
  "last_before P 0 = None"
"last_before P (Suc n) = (if P n then Some n else last_before P n)"

lemma last_before_None: "last_before P n = None ==> m < n ==> ¬P m"
proof (induction P n rule: last_before.induct)
  case (2 P n)
  then show ?case
    by (cases "m = n") (auto split: if_splits)
qed (auto split: if_splits)

lemma last_before_Some: "last_before P n = Some m ==> m < n P m (k {m<..<n}. ¬P k)"
  apply (induction P n rule: last_before.induct)
   apply (auto split: if_splits)
  apply (metis greaterThanLessThan_iff less_antisym)
  done

inductive wf_vydra :: "('a, 't :: timestamp) formula ==> nat ==> nat ==> ('a, 't, 'h) vydra_aux ==> bool" where
  "wf_vydra phi i n w ==> ru n w = None ==> wf_vydra (Prev I phi) (Suc i) (Suc n) VYDRA_None"
"wf_vydra phi i n w ==> ru n w = None ==> wf_vydra (Next I phi) i (Suc n) VYDRA_None"
"reaches_on run_hd init_hd es sub' ==> length es = i ==> wf_vydra (Bool b) i n (VYDRA_Bool b sub')"
"reaches_on run_hd init_hd es sub' ==> length es = i ==> wf_vydra (Atom a) i n (VYDRA_Atom a sub')"
"wf_vydra phi i n v ==> wf_vydra (Neg phi) i (Suc n) (VYDRA_Neg v)"
"wf_vydra phi i n v ==> wf_vydra psi i n v' ==> wf_vydra (Bin f phi psi) i (Suc n) (VYDRA_Bin f v v')"
"wf_vydra phi i n v ==> reaches_on run_hd init_hd es sub' ==> length es = i ==>
   wf_vydra (Prev I phi) i (Suc n) (VYDRA_Prev I v sub' (case i of 0 ==> None | Suc j ==> Some (τ σ j, sat phi j)))"
"wf_vydra phi i n v ==> reaches_on run_hd init_hd es sub' ==> length es = i ==>
   wf_vydra (Next I phi) (i - 1) (Suc n) (VYDRA_Next I v sub' (case i of 0 ==> None | Suc j ==> Some (τ σ j)))"
"wf_vydra phi i n vphi ==> wf_vydra psi j n vpsi ==> j i ==>
   reaches_on ru_t l_t0 es sub' ==> length es = j ==> (t. t set es ==> memL t (τ σ i) I) ==>
   cphi = i - (case last_before (λk. ¬sat phi k) i of None ==> 0 | Some k ==> Suc k) ==> cpsi = i - j ==>
   cppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (i - k)) ==>
   tppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (τ σ k)) ==>
   wf_vydra (Since phi I psi) i (Suc n) (VYDRA_Since I vphi vpsi sub' cphi cpsi cppsi tppsi)"
"wf_vydra phi j n vphi ==> wf_vydra psi j n vpsi ==> i j ==>
   reaches_on ru_t l_t0 es back ==> length es = i ==>
   reaches_on ru_t l_t0 es' front ==> length es' = j ==> (t. t set es' ==> memR (τ σ i) t I) ==>
   c = j - i ==> z = (case j of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k)) ==>
   (k. k {i..<j - 1} ==> sat phi k (memL (τ σ i) (τ σ k) I ¬sat psi k)) ==>
   wf_vydra (Until phi I psi) i (Suc n) (VYDRA_Until I back vphi vpsi front c z)"
"valid_window_matchP args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w ==>
    n msize_regex r ==> qf = state_cnt r ==>
    transs = iarray_of_list (build_nfa_impl r (0, qf, [])) ==>
    args = init_args ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (ru_t, read_t) (run_subs (ru n)) ==>
    wf_vydra (MatchP I r) i (Suc n) (VYDRA_MatchP I transs qf w)"
"valid_window_matchF args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w ==>
    n msize_regex r ==> qf = state_cnt r ==>
    transs = iarray_of_list (build_nfa_impl r (0, qf, [])) ==>
    args = init_args ({0}, NFA.delta' transs qf, NFA.accept' transs qf)
      (ru_t, read_t) (run_subs (ru n)) ==>
    wf_vydra (MatchF I r) i (Suc n) (VYDRA_MatchF I transs qf w)"

lemma reach_run_subs_len:
  assumes reaches_ons: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) rho vs"
  shows "length vs = length (collect_subfmlas r [])"
  using reaches_ons run_subs_lD
  by (induction "map (su n) (collect_subfmlas r [])" rho vs rule: reaches_on_rev_induct) fastforce+

lemma reach_run_subs_run:
  assumes reaches_ons: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) rho vs"
    and subfmla: "j < length (collect_subfmlas r [])" "phi = collect_subfmlas r [] ! j"
  shows "rho'. reaches_on (ru n) (su n phi) rho' (vs ! j) length rho' = length rho"
  using reaches_ons subfmla
proof (induction "map (su n) (collect_subfmlas r [])" rho vs rule: reaches_on_rev_induct)
  case 1
  then show ?case
    by (auto intro: reaches_on.intros)
next
  case (2 s' v vs' s'')
  note len_s'_vs = reach_run_subs_len[OF 2(1)]
  obtain rho' where reach_s'_vs: "reaches_on (ru n) (su n phi) rho' (s' ! j)"
    "length rho' = length vs'"
    using 2(2)[OF 2(4,5)]
    by auto
  note run_subslD = run_subs_lD[OF 2(3)]
  note run_subsvD = run_subs_vD[OF 2(32(4)[unfolded len_s'_vs[symmetric]]]
  obtain vj' tj bj where vj'_def"ru n (s' ! j) = Some (vj', tj, bj)"
    "s'' ! j = vj'" "IArray.sub v j = bj"
    using run_subsvD by auto
  obtain rho'' where rho''_def"reaches_on (ru n) (su n phi) rho'' (s'' ! j)"
    "length rho'' = Suc (length vs')"
    using reaches_on_app[OF reach_s'_vs(1) vj'_def(1)] vj'_def(2) reach_s'_vs(2)
    by auto
  then show ?case
    using conjunct1[OF run_subslD, unfolded len_s'_vs[symmetric]]
    by auto
qed

lemma IArray_nth_equalityI: "IArray.length xs = length ys ==>
  (i. i < IArray.length xs ==> IArray.sub xs i = ys ! i) ==> xs = IArray ys"
  by (induction xs arbitrary: ys) (auto intro: nth_equalityI)

lemma bs_sat:
  assumes IH: "phi i v v' b. phi set (collect_subfmlas r []) ==> wf_vydra phi i n v ==> ru n v = Some (v', b) ==> snd b = sat phi i"
    and reaches_ons: "j. j < length (collect_subfmlas r []) ==> wf_vydra (collect_subfmlas r [] ! j) i n (vs ! j)"
    and run_subs: "run_subs (ru n) vs = Some (vs', bs)" "length vs = length (collect_subfmlas r [])"
  shows "bs = iarray_of_list (map (λphi. sat phi i) (collect_subfmlas r []))"
proof -
  have "j. j < length (collect_subfmlas r []) ==>
    IArray.sub bs j = sat (collect_subfmlas r [] ! j) i"
  proof -
    fix j
    assume lassm: "j < length (collect_subfmlas r [])"
    define phi where "phi = collect_subfmlas r [] ! j"
    have phi_in_set: "phi set (collect_subfmlas r [])"
      using lassm
      by (auto simp: phi_def)
    have wf: "wf_vydra phi i n (vs ! j)"
      using reaches_ons lassm phi_def
      by metis
    show "IArray.sub bs j = sat (collect_subfmlas r [] ! j) i"
      using IH(1)[OF phi_in_set wf] run_subs_vD[OF run_subs(1) lassm[folded run_subs(2)]]
      unfolding phi_def[symmetric]
      by auto
  qed
  moreover have "length (IArray.list_of bs) = length vs"
    using run_subs(1)
    by (auto simp: run_subs_def Let_def iarray_of_list_def split: if_splits)
  ultimately show ?thesis
    using run_subs(2)
    by (auto simp: iarray_of_list_def intro!: IArray_nth_equalityI)
qed

lemma run_induct[case_names Bool Atom Neg Bin Prev Next Since Until MatchP MatchF, consumes 1]:
  fixes phi :: "('a, 't) formula"
  assumes "msize_fmla phi n" "(b n. P n (Bool b))" "(a n. P n (Atom a))"
    "(n phi. msize_fmla phi n ==> P n phi ==> P (Suc n) (Neg phi))"
    "(n f phi psi. msize_fmla (Bin f phi psi) Suc n ==> P n phi ==> P n psi ==>
      P (Suc n) (Bin f phi psi))"
    "(n I phi. msize_fmla phi n ==> P n phi ==> P (Suc n) (Prev I phi))"
    "(n I phi. msize_fmla phi n ==> P n phi ==> P (Suc n) (Next I phi))"
    "(n I phi psi. msize_fmla phi n ==> msize_fmla psi n ==> P n phi ==> P n psi ==> P (Suc n) (Since phi I psi))"
    "(n I phi psi. msize_fmla phi n ==> msize_fmla psi n ==> P n phi ==> P n psi ==> P (Suc n) (Until phi I psi))"
    "(n I r. msize_fmla (MatchP I r) Suc n ==> (x. msize_fmla x n ==> P n x) ==>
      P (Suc n) (MatchP I r))"
    "(n I r. msize_fmla (MatchF I r) Suc n ==> (x. msize_fmla x n ==> P n x) ==>
      P (Suc n) (MatchF I r))"
  shows "P n phi"
  using assms(1)
proof (induction n arbitrary: phi rule: nat_less_induct)
  case (1 n)
  show ?case
  proof (cases n)
    case 0
    show ?thesis
      using 1 assms(2-)
      by (cases phi) (auto simp: 0)
  next
    case (Suc m)
    show ?thesis
      using 1 assms(2-)
      by (cases phi) (auto simp: Suc)
  qed
qed

lemma wf_vydra_sub: "msize_fmla φ n ==> wf_vydra φ 0 n (su n φ)"
proof (induction n φ rule: run_induct)
  case (Prev n I phi)
  then show ?case
    using wf_vydra.intros(7)[where ?i=0, OF _ reaches_on.intros(1)]
    by auto
next
  case (Next n I phi)
  then show ?case
    using wf_vydra.intros(8)[where ?i=0, OF _ reaches_on.intros(1)]
    by auto
next
  case (MatchP n I r)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  let ?args = "init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  show ?case
    using MatchP valid_init_window[of ?args l_t0 "map (su n) (collect_subfmlas r [])", simplified]
    by (auto simp: Let_def valid_window_matchP_def split: option.splits intro: reaches_on.intros
        intro!: wf_vydra.intros(11)[where ?xs="[]", OF _ _ refl refl refl])
next
  case (MatchF n I r)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  let ?args = "init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  show ?case
    using MatchF valid_init_window[of ?args l_t0 "map (su n) (collect_subfmlas r [])", simplified]
    by (auto simp: Let_def valid_window_matchF_def split: option.splits intro: reaches_on.intros
        intro!: wf_vydra.intros(12)[where ?xs="[]", OF _ _ refl refl refl])
qed (auto simp: Let_def intro: wf_vydra.intros reaches_on.intros)

lemma ru_t_Some: "e' et. ru_t e = Some (e', et)" if reaches_Suc_i: "reaches_on run_hd init_hd fs f" "length fs = Suc i"
  and aux: "reaches_on ru_t l_t0 es e" "length es i" for es e
proof -
  obtain fs' ft where ft_def: "reaches_on ru_t l_t0 (map fst (fs' :: ('t × 'a set) list)) (Some (f, ft))"
    "map fst fs = map fst fs' @ [ft]" "length fs' = i"
    using reaches_Suc_i
    by (cases fs rule: rev_cases) (auto dest!: reaches_on_split_last reach_event_t0_t)
  show ?thesis
  proof (cases "length es = i")
    case True
    have e_def: "e = Some (f, ft)"
      using reaches_on_inj[OF aux(1) ft_def(1)]
      by (auto simp: True ft_def(3))
    then show ?thesis
      by (cases "run_hd f") (auto simp: e_def)
  next
    case False
    obtain s' s'' where split: "reaches_on ru_t l_t0 (take (length es) (map fst fs')) s'"
      "ru_t s' = Some (s'', map fst fs' ! (length es))"
      using reaches_on_split[OF ft_def(1), where ?i="length es"] False aux(2)
      by (auto simp: ft_def(3))
    show ?thesis
      using reaches_on_inj[OF aux(1) split(1)] aux(2)
      by (auto simp: ft_def(3) split(2))
  qed
qed

lemma vydra_sound_aux:
  assumes "msize_fmla φ n" "wf_vydra φ i n v" "ru n v = Some (v', t, b)" "bounded_future_fmla φ" "wf_fmla φ"
  shows "wf_vydra φ (Suc i) n v' (es e. reaches_on run_hd init_hd es e length es = Suc i) t = τ σ i b = sat φ i"
  using assms
proof (induction n φ arbitrary: i v v' t b rule: run_induct)
  case (Bool β n)
  then show ?case
    using reaches_on_run_hd reaches_on_app wf_vydra.intros(3)[OF reaches_on_app refl]
    by (fastforce elim!: wf_vydra.cases[of _ _ _ "v"] split: option.splits)
next
  case (Atom a n)
  then show ?case
    using reaches_on_run_hd reaches_on_app wf_vydra.intros(4)[OF reaches_on_app refl]
    by (fastforce elim!: wf_vydra.cases[of _ _ _ v] split: option.splits)
next
  case (Neg n x)
  have IH: "wf_vydra x i n v ==> ru n v = Some (v', t, b) ==> wf_vydra x (Suc i) n v' (es e. reaches_on run_hd init_hd es e length es = Suc i) t = τ σ i b = sat x i" for v v' t b
    using Neg(2,5,6)
    by auto
  show ?case
    apply (rule wf_vydra.cases[OF Neg(3)])
    using Neg(4) IH wf_vydra.intros(5)
    by (fastforce split: option.splits)+
next
  case (Bin n f x1 x2)
  have IH1: "wf_vydra x1 i n v ==> ru n v = Some (v', t, b) ==> wf_vydra x1 (Suc i) n v' (es e. reaches_on run_hd init_hd es e length es = Suc i) t = τ σ i b = sat x1 i" for v v' t b
    using Bin(2,6,7)
    by auto
  have IH2: "wf_vydra x2 i n v ==> ru n v = Some (v', t, b) ==> wf_vydra x2 (Suc i) n v' t = τ σ i b = sat x2 i" for v v' t b
    using Bin(3,6,7)
    by auto
  show ?case
    apply (rule wf_vydra.cases[OF Bin(4)])
    using Bin(5) IH1 IH2 wf_vydra.intros(6)
    by (fastforce split: option.splits)+
next
  case (Prev n I phi)
  show ?case
  proof (cases i)
    case 0
    then show ?thesis
      using Prev run_hd_sound[OF reaches.intros(1)] wf_vydra.intros(7)[OF _ reaches_on.intros(2)[OF _ reaches_on.intros(1)], where ?i="Suc 0", simplified]
      by (fastforce split: nat.splits option.splits dest!: reaches_on_NilD elim!: wf_vydra.cases[of _ _ _ v] intro: wf_vydra.intros(1) reaches_on.intros(2)[OF _ reaches_on.intros(1)])
  next
    case (Suc j)
    obtain vphi es sub where v_def: "v = VYDRA_Prev I vphi sub (Some (τ σ j, sat phi j))"
      "wf_vydra phi i n vphi" "reaches_on run_hd init_hd es sub" "length es = i"
      using Prev(3,4)
      by (auto simp: Suc elim!: wf_vydra.cases[of _ _ _ v])
    obtain sub' X where run_sub: "run_hd sub = Some (sub', (t, X))"
      using Prev(4)
      by (auto simp: v_def(1) Let_def split: option.splits)
    note reaches_sub' = reaches_on_app[OF v_def(3) run_sub]
    have t_def: "t = τ σ (Suc j)"
      using reaches_on_run_hd[OF v_def(3) run_sub]
      by (auto simp: Suc v_def(2,4))
    show ?thesis
    proof (cases "v' = VYDRA_None")
      case v'_def: True
      show ?thesis
        using Prev(4) v_def(2) reaches_sub'
        by (auto simp: Suc Let_def v_def(1,4) v'_def run_sub t_def split: option.splits intro: wf_vydra.intros(1))
    next
      case False
      obtain vphi' where ru_vphi: "ru n vphi = Some (vphi', (τ σ i, sat phi i))"
        using Prev(2)[OF v_def(2)] Prev(4,5,6) False
        by (auto simp: v_def(1) Let_def split: option.splits)
      have wf': "wf_vydra phi (Suc (Suc j)) n vphi'"
        using Prev(2)[OF v_def(2) ru_vphi] Prev(5,6)
        by (auto simp: Suc)
      show ?thesis
        using Prev(4) wf_vydra.intros(7)[OF wf' reaches_sub'] reaches_sub'
        by (auto simp: Let_def Suc t_def v_def(1,4) run_sub ru_vphi)
    qed
  qed
next
  case (Next n I phi)
  obtain w sub to es where v_def: "v = VYDRA_Next I w sub to" "wf_vydra phi (length es) n w"
    "reaches_on run_hd init_hd es sub" "length es = (case to of None ==> 0 | _ ==> Suc i)"
    "case to of None ==> i = 0 | Some told ==> told = τ σ i"
    using Next(3,4)
    by (auto elim!: wf_vydra.cases[of _ _ _ v] split: option.splits nat.splits)
  obtain sub' tnew X where run_sub: "run_hd sub = Some (sub', (tnew, X))"
    using Next(4)
    by (auto simp: v_def(1) split: option.splits)
  have tnew_def: "tnew = τ σ (length es)"
    using reaches_on_run_hd[OF v_def(3) run_sub]
    by auto
  have aux: ?case if aux_assms: "wf_vydra phi (Suc i) n w"
    "ru (Suc n) (VYDRA_Next I w sub (Some t0)) = Some (v', t, b)"
    "reaches_on run_hd init_hd es sub" "length es = Suc i" "t0 = τ σ i" for w sub t0 es
    using aux_assms(1,2,5) wf_vydra.intros(2)[OF aux_assms(1)]
      Next(2)[where ?i="Suc i" and ?v="w"Next(5,6) reaches_on_run_hd[OF aux_assms(3)]
      wf_vydra.intros(8)[OF _ reaches_on_app[OF aux_assms(3)], where ?phi=phi and ?i="Suc (Suc i)" and ?n="n"] aux_assms(3)
    by (auto simp: run_sub aux_assms(4,5) split: option.splits if_splits)
  show ?case
  proof (cases to)
    case None
    obtain w' z where w_def: "ru (Suc n) v = ru (Suc n) (VYDRA_Next I w' sub' (Some tnew))"
      "ru n w = Some (w', z)"
      using Next(4)
      by (cases "ru n w") (auto simp: v_def(1) run_sub None split: option.splits)
    have wf: "wf_vydra phi (Suc i) n w'"
      using v_def w_def(2Next(2,5,6)
      by (cases z) (auto simp: None intro: wf_vydra.intros(1))
    show ?thesis
      using aux[OF wf Next(4)[unfolded w_def(1)] reaches_on_app[OF v_def(3) run_sub]] v_def(4,5) tnew_def
      by (auto simp: None)
  next
    case (Some z)
    show ?thesis
      using aux[OF _ _ v_def(3), where ?w="w"] v_def(2,4,5Next(4)
      by (auto simp: v_def(1) Some simp del: run.simps)
  qed
next
  case (Since n I phi psi)
  obtain vphi vpsi e cphi cpsi cppsi tppsi j es where v_def:
    "v = VYDRA_Since I vphi vpsi e cphi cpsi cppsi tppsi"
    "wf_vydra phi i n vphi" "wf_vydra psi j n vpsi" "j i"
    "reaches_on ru_t l_t0 es e" "length es = j" "t. t set es ==> memL t (τ σ i) I"
    "cphi = i - (case last_before (λk. ¬sat phi k) i of None ==> 0 | Some k ==> Suc k)" "cpsi = i - j"
    "cppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (i - k))"
    "tppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (τ σ k))"
    using Since(5)
    by (auto elim: wf_vydra.cases)
  obtain vphi' b1 where run_vphi: "ru n vphi = Some (vphi', t, b1)"
    using Since(6)
    by (auto simp: v_def(1) Let_def split: option.splits)
  obtain fs f where wf_vphi': "wf_vydra phi (Suc i) n vphi'"
    and reaches_Suc_i: "reaches_on run_hd init_hd fs f" "length fs = Suc i"
    and t_def: "t = τ σ i" and b1_def: "b1 = sat phi i"
    using Since(3)[OF v_def(2) run_vphi] Since(7,8)
    by auto
  note ru_t_Some = ru_t_Some[OF reaches_Suc_i]
  define loop_inv where "loop_inv = (λ(vpsi, e, cpsi :: nat, cppsi, tppsi).
    let j = Suc i - cpsi in cpsi Suc i
    wf_vydra psi j n vpsi (es. reaches_on ru_t l_t0 es e length es = j (t set es. memL t (τ σ i) I))
    cppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (Suc i - k))
    tppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (τ σ k)))"
  define loop_init where "loop_init = (vpsi, e, Suc cpsi, map_option Suc cppsi, tppsi)"
  obtain vpsi' e' cpsi' cppsi' tppsi' where loop_def: "while_break (while_since_cond I t) (while_since_body run_hd (ru n)) loop_init =
    Some (vpsi', e', cpsi', cppsi', tppsi')"
    using Since(6)
    by (auto simp: v_def(1) run_vphi loop_init_def Let_def split: option.splits)
  have j_def: "j = i - cpsi"
    using v_def(4,9)
    by auto
  have "cpsi i"
    using v_def(9)
    by auto
  then have loop_inv_init: "loop_inv loop_init"
    using v_def(3,5,6,7,10,11) last_before_Some
    by (fastforce simp: loop_inv_def loop_init_def Let_def j_def split: option.splits)
  have wf_loop: "wf {(s', s). loop_inv s while_since_cond I t s Some s' = while_since_body run_hd (ru n) s}"
    by (auto intro: wf_subset[OF wf_since])
  have step_loop: "loop_inv s'" if loop_assms: "loop_inv s" "while_since_cond I t s" "while_since_body run_hd (ru n) s = Some s'" for s s'
  proof -
    obtain vpsi e cpsi cppsi tppsi where s_def: "s = (vpsi, e, cpsi, cppsi, tppsi)"
      by (cases s) auto
    define j where "j = Suc i - cpsi"
    obtain es where loop_before: "cpsi Suc i" "wf_vydra psi j n vpsi"
      "reaches_on ru_t l_t0 es e" "length es = j" "t. t set es ==> memL t (τ σ i) I"
      "cppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (Suc i - k))"
      "tppsi = (case last_before (sat psi) j of None ==> None | Some k ==> Some (τ σ k))"
      using loop_assms(1)
      by (auto simp: s_def j_def loop_inv_def Let_def)
    obtain tt h where tt_def: "read_t e = Some tt" "memL tt t I" "e = Some (h, tt)"
      using ru_t_Some[OF loop_before(3)] loop_before(4) loop_assms(2)
      by (cases e) (fastforce simp: while_since_cond_def s_def j_def split: option.splits)+
    obtain e' where e'_def"reaches_on ru_t l_t0 (es @ [tt]) e'" "ru_t e = Some (e', tt)"
      using reaches_on_app[OF loop_before(3)] tt_def(1)
      by (cases "run_hd h") (auto simp: tt_def(3))
    obtain vpsi' t' b' where run_vpsi: "ru n vpsi = Some (vpsi', (t', b'))"
      using loop_assms(3)
      by (auto simp: while_since_body_def s_def Let_def split: option.splits)
    have wf_psi': "wf_vydra psi (Suc j) n vpsi'" and t'_def"t' = τ σ j" and b'_def"b' = sat psi j"
      using Since(4)[OF loop_before(2) run_vpsi] Since(7,8)
      by auto
    define j' where j'_def"j' = Suc i - (cpsi - Suc 0)"
    have cpsi_pos: "cpsi > 0"
      using loop_assms(2)
      by (auto simp: while_since_cond_def s_def)
    have j'_j: "j' = Suc j"
      using loop_before(1) cpsi_pos
      by (auto simp: j'_def j_def)
    define cppsi' where "cppsi' = (if b' then Some cpsi else cppsi)"
    define tppsi' where "tppsi' = (if b' then Some t' else tppsi)"
    have cppsi': "cppsi' = (case last_before (sat psi) j' of None ==> None | Some k ==> Some (Suc i - k))"
      using cpsi_pos loop_before(1)
      by (auto simp: cppsi'_def b'_def j'_j loop_before(6) j_def)
    have tppsi': "tppsi' = (case last_before (sat psi) j' of None ==> None | Some k ==> Some (τ σ k))"
      by (auto simp: tppsi'_def t'_def b'_def j'_j loop_before(7) split: option.splits)
    have s'_def"s' = (vpsi', fst (the (ru_t e)), cpsi - Suc 0, cppsi', tppsi')"
      using loop_assms(3)
      by (auto simp: while_since_body_def s_def run_vpsi cppsi'_def tppsi'_def)
    show ?thesis
      using loop_before(1,4,5) tt_def(2) wf_psi'[folded j'_j] cppsi' tppsi' e'_def(1)
      by (fastforce simp: loop_inv_def s'_def j'_def[symmetric] e'_def(2) j'_j t_def)
  qed
  have loop: "loop_inv (vpsi', e', cpsi', cppsi', tppsi')" "¬while_since_cond I t (vpsi', e', cpsi', cppsi', tppsi')"
    using while_break_sound[where ?P="loop_inv" and ?Q="λs. loop_inv s ¬while_since_cond I t s", OF step_loop _ wf_loop loop_inv_init]
    by (auto simp: loop_def)
  define cphi' where "cphi' = (if b1 then Suc cphi else 0)"
  have v'_def"v' = VYDRA_Since I vphi' vpsi' e' cphi' cpsi' cppsi' tppsi'"
    and b_def: "b = (case cppsi' of None ==> False | Some k ==> k - 1 cphi' memR (the tppsi') t I)"
    using Since(6)
    by (auto simp: v_def(1) run_vphi loop_init_def[symmetric] loop_def cphi'_def Let_def split: option.splits)
  have read_t_e': "cpsi' > 0 ==> read_t e' = None ==> False"
    using loop(1) ru_t_Some[where ?e=e'] run_t_read
    by (fastforce simp: loop_inv_def Let_def)
  define j' where "j' = Suc i - cpsi'"
  have wf_vpsi': "wf_vydra psi j' n vpsi'" and cpsi'_le_Suc_i: "cpsi' Suc i"
    and cppsi'_def"cppsi' = (case last_before (sat psi) j' of None ==> None | Some k ==> Some (Suc i - k))"
    and tppsi'_def"tppsi' = (case last_before (sat psi) j' of None ==> None | Some k ==> Some (τ σ k))"
    using loop(1)
    by (auto simp: loop_inv_def j'_def[symmetric])
  obtain es' where es'_def"reaches_on ru_t l_t0 es' e'" "length es' = j'" "t. t set es' ==> memL t (τ σ i) I"
    using loop(1)
    by (auto simp: loop_inv_def j'_def[symmetric])
  have wf_v': "wf_vydra (Since phi I psi) (Suc i) (Suc n) v'"
    and cphi'_sat: "cphi' = Suc i - (case last_before (λk. ¬sat phi k) (Suc i) of None ==> 0 | Some k ==> Suc k)"
    using cpsi'_le_Suc_i last_before_Some es'_def(3) memL_mono'[OF _ τ_mono[of i "Suc i" σ]]
    by (force simp: v'_def cppsi'_def tppsi'_def j'_def cphi'_def b1_def v_def(8) split: option.splits
        intro!: wf_vydra.intros(9)[OF wf_vphi' wf_vpsi' _ es'_def(1-2)])+
  have "j' = Suc i ¬memL (τ σ j') (τ σ i) I"
    using loop(2) j'_def read_t_e' ru_t_tau[OF es'_def(1)] read_t_run[where ?run_hd=run_hd]
    by (fastforce simp: while_since_cond_def es'_def(2) t_def split: option.splits)
  then have tau_k_j': "k i ==> memL (τ σ k) (τ σ i) I k < j'" for k
    using ru_t_tau_in[OF es'_def(1)] es'_def(3) τ_mono[of j' k σ] memL_mono
    by (fastforce simp: es'_def(2) in_set_conv_nth)
  have b_sat: "b = sat (Since phi I psi) i"
  proof (rule iffI)
    assume b: "b"
    obtain m where m_def: "last_before (sat psi) j' = Some m" "i - m cphi'" "memR (τ σ m) (τ σ i) I"
      using b
      by (auto simp: b_def t_def cppsi'_def tppsi'_def split: option.splits)
    note aux = last_before_Some[OF m_def(1)]
    have mem: "mem (τ σ m) (τ σ i) I"
      using m_def(3) tau_k_j' aux
      by (auto simp: mem_def j'_def)
    have sat_phi: "sat phi x" if "m < x" "x i" for x
      using m_def(2) that le_neq_implies_less
      by (fastforce simp: cphi'_sat dest: last_before_None last_before_Some split: option.splits if_splits)
    show "sat (Since phi I psi) i"
      using aux mem sat_phi
      by (auto simp: j'_def intro!: exI[of _ m])
  next
    assume sat: "sat (Since phi I psi) i"
    then obtain k where k_def: "k i" "mem (τ σ k) (τ σ i) I" "sat psi k" "k'. k < k' k' i ==> sat phi k'"
      by auto
    have k_j': "k < j'"
      using tau_k_j'[OF k_def(1)] k_def(2)
      by (auto simp: mem_def)
    obtain m where m_def: "last_before (sat psi) j' = Some m"
      using last_before_None[where ?P="sat psi" and ?n=j' and ?m=k] k_def(3) k_j'
      by (cases "last_before (sat psi) j'") auto
    have cppsi'_Some: "cppsi' = Some (Suc i - m)"
      by (auto simp: cppsi'_def m_def)
    have tppsi'_Some: "tppsi' = Some (τ σ m)"
      by (auto simp: tppsi'_def m_def)
    have m_k: "k m"
      using last_before_Some[OF m_def] k_def(3) k_j'
      by auto
    have tau_i_m: "memR (τ σ m) (τ σ i) I"
      using τ_mono[OF m_k, where ?s=σ] memR_mono k_def(2)
      by (auto simp: mem_def)
    have "i - m cphi'"
      using k_def(1) k_def(4) m_k
      apply (cases "k = i")
       apply (auto simp: cphi'_sat b1_def dest!: last_before_Some split: option.splits)
      apply (metis diff_le_mono2 le_neq_implies_less le_trans less_imp_le_nat nat_le_linear)
      done
    then show "b"
      using tau_i_m
      by (auto simp: b_def t_def cppsi'_Some tppsi'_Some)
  qed
  show ?case
    using wf_v' reaches_Suc_i
    by (auto simp: t_def b_sat)
next
  case (Until n I phi psi)
  obtain "back" vphi vpsi front c z es es' j where v_def:
    "v = VYDRA_Until I back vphi vpsi front c z"
    "wf_vydra phi j n vphi" "wf_vydra psi j n vpsi" "i j"
    "reaches_on ru_t l_t0 es back" "length es = i"
    "reaches_on ru_t l_t0 es' front" "length es' = j" "t. t set es' ==> memR (τ σ i) t I"
    "c = j - i" "z = (case j of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k))"
    "k. k {i..<j - 1} ==> sat phi k (memL (τ σ i) (τ σ k) I ¬sat psi k)"
    using Until(5)
    by (auto elim: wf_vydra.cases)
  define loop_init where "loop_init = (vphi, vpsi, front, c, z)"
  obtain back' vphi' vpsi' epsi' c' zo' zt zb1 zb2 where run_back: "ru_t back = Some (back', t)"
    and loop_def: "while_break (while_until_cond I t) (while_until_body run_hd (ru n)) loop_init = Some (vphi', vpsi', epsi', c', zo')"
    and v'_def"v' = VYDRA_Until I back' vphi' vpsi' epsi' (c' - 1) zo'"
    and c'_pos: "¬c' = 0"
    and zo'_Some: "zo' = Some (zt, (zb1, zb2))"
    and b_def: "b = (zb2 memL t zt I)"
    using Until(6)
    apply (auto simp: v_def(1) Let_def loop_init_def[symmetric] split: option.splits nat.splits if_splits)
    done
  define j' where "j' = i + c'"
  have j_eq: "j = i + c"
    using v_def(4)
    by (auto simp: v_def(10))
  have t_def: "t = τ σ i"
    using ru_t_tau[OF v_def(5) run_back]
    by (auto simp: v_def(6))
  define loop_inv where "loop_inv = (λ(vphi, vpsi, epsi, c, zo).
    let j = i + c in
    wf_vydra phi j n vphi wf_vydra psi j n vpsi
    (gs. reaches_on ru_t l_t0 gs epsi length gs = j (t. t set gs memR (τ σ i) t I))
    zo = (case j of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k))
    (k. k {i..<j - 1} sat phi k (memL (τ σ i) (τ σ k) I ¬sat psi k)))"
  have loop_inv_init: "loop_inv loop_init"
    using v_def(2,3,7,9,12)
    by (auto simp: loop_inv_def loop_init_def j_eq[symmetric] v_def(8,11))
  have loop_step: "loop_inv s'" if loop_assms: "loop_inv s" "while_until_cond I t s" "while_until_body run_hd (ru n) s = Some s'" for s s'
  proof -
    obtain vphi_cur vpsi_cur epsi_cur c_cur zo_cur where s_def: "s = (vphi_cur, vpsi_cur, epsi_cur, c_cur, zo_cur)"
      by (cases s) auto
    define j_cur where "j_cur = i + c_cur"
    obtain epsi'_cur t'_cur vphi'_cur tphi_cur bphi_cur vpsi'_cur tpsi_cur bpsi_cur where
      run_epsi: "ru_t epsi_cur = Some (epsi'_cur, t'_cur)"
      and run_vphi: "ru n vphi_cur = Some (vphi'_cur, (tphi_cur, bphi_cur))"
      and run_vpsi: "ru n vpsi_cur = Some (vpsi'_cur, (tpsi_cur, bpsi_cur))"
      using loop_assms(2,3)
      apply (auto simp: while_until_cond_def while_until_body_def s_def split: option.splits dest: read_t_run[where ?run_hd=run_hd])
      done
    have wf: "wf_vydra phi j_cur n vphi_cur" "wf_vydra psi j_cur n vpsi_cur"
      and zo_cur_def: "zo_cur = (case j_cur of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k))"
      using loop_assms(1)
      by (auto simp: loop_inv_def s_def j_cur_def[symmetric])
    have wf': "wf_vydra phi (Suc j_cur) n vphi'_cur" "tphi_cur = τ σ j_cur" "bphi_cur = sat phi j_cur"
      "wf_vydra psi (Suc j_cur) n vpsi'_cur" "tpsi_cur = τ σ j_cur" "bpsi_cur = sat psi j_cur"
      using Until(3)[OF wf(1) run_vphi] Until(4)[OF wf(2) run_vpsi] Until(7,8)
      apply (auto)
      done
    have s'_def"s' = (vphi'_cur, vpsi'_cur, epsi'_cur, Suc c_cur, Some (t'_cur, (bphi_cur, bpsi_cur)))"
      using loop_assms(3)
      by (auto simp: while_until_body_def s_def run_epsi run_vphi run_vpsi)
    obtain gs_cur where gs_cur_def: "reaches_on ru_t l_t0 gs_cur epsi_cur"
      "length gs_cur = j_cur" "t. t set gs_cur ==> memR (τ σ i) t I"
      using loop_assms(1)
      by (auto simp: loop_inv_def s_def j_cur_def[symmetric])
    have t'_cur_def: "t'_cur = τ σ j_cur"
      using ru_t_tau[OF gs_cur_def(1) run_epsi]
      by (auto simp: gs_cur_def(2))
    have t'_cur_right_I: "memR t t'_cur I"
      using loop_assms(2) run_t_read[OF run_epsi]
      by (auto simp: while_until_cond_def s_def)
    have c_cur_zero: "c_cur = 0 ==> j_cur = i"
      by (auto simp: j_cur_def)
    have "k {i..<Suc j_cur - 1} ==> sat phi k (memL (τ σ i) (τ σ k) I ¬sat psi k)" for k
      using loop_assms(1,2)
      by (cases "k = j_cur - Suc 0") (auto simp: while_until_cond_def loop_inv_def j_cur_def[symmetric] zo_cur_def s_def until_ready_def t_def split: nat.splits dest: c_cur_zero)
    then show ?thesis
      using wf' t'_cur_right_I
      using reaches_on_app[OF gs_cur_def(1) run_epsi] gs_cur_def(2,3)
      by (auto simp: loop_inv_def s'_def j_cur_def[symmetric] t_def t'_cur_def intro!: exI[of _ "gs_cur @ [t'_cur]"])
  qed
  have wf_loop: "wf {(s', s). loop_inv s while_until_cond I t s Some s' = while_until_body run_hd (ru n) s}"
  proof -
    obtain m where m_def: "¬τ σ m τ σ i + right I"
      using ex_lt_τ[where ?x="right I" and ?s=σ] Until(7)
      by auto
    define X where "X = {(s', s). loop_inv s while_until_cond I t s Some s' = while_until_body run_hd (ru n) s}"
    have "memR t (τ σ (i + c)) I ==> i + c < m" for c
      using m_def order_trans[OF τ_mono[where ?i=m and ?j="i + c" and ?s=σ]]
      by (fastforce simp: t_def dest!: memR_dest)
    then have "X measure (λ(vphi, vpsi, epsi, c, zo). m - c)"
      by (fastforce simp: X_def while_until_cond_def while_until_body_def loop_inv_def Let_def split: option.splits
          dest!: read_t_run[where ?run_hd=run_hd] dest: ru_t_tau)
    then show ?thesis
      using wf_subset
      by (auto simp: X_def[symmetric])
  qed
  have loop: "loop_inv (vphi', vpsi', epsi', c', zo')" "¬while_until_cond I t (vphi', vpsi', epsi', c', zo')"
    using while_break_sound[where ?Q="λs. loop_inv s ¬while_until_cond I t s", OF _ _ wf_loop loop_inv_init] loop_step
    by (auto simp: loop_def)
  have tau_right_I: "k < j' ==> memR (τ σ i) (τ σ k) I" for k
    using loop(1) ru_t_tau_in
    by (auto simp: loop_inv_def j'_def[symmetric] in_set_conv_nth)
  have read_t_epsi': "read_t epsi' = Some et ==> et = τ σ j'" for et
    using loop(1) ru_t_tau
    by (fastforce simp: loop_inv_def Let_def j'_def dest!: read_t_run[where ?run_hd=run_hd])
  have end_cond: "until_ready I t c' zo' ¬(memR (τ σ i) (τ σ j') I)"
    unfolding t_def[symmetric]
    using Until(6) c'_pos loop(2)[unfolded while_until_cond_def]
    by (auto simp: until_ready_def v_def(1) run_back loop_init_def[symmetric] loop_def zo'_Some split: if_splits option.splits nat.splits dest: read_t_epsi')
  have Suc_i_le_j': "Suc i j'" and c'_j': "c' - Suc 0 = j' - Suc i"
    using end_cond c'_pos
    by (auto simp: until_ready_def j'_def split: nat.splits)
  have zo'_def"zo' = (case j' of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k))"
    and sat_phi: "k {i..<j' - 1} ==> sat phi k"
    and not_sat_psi: "k {i..<j' - 1} ==> memL (τ σ i) (τ σ k) I ==> ¬sat psi k" for k
    using loop(1)
    by (auto simp: loop_inv_def j'_def[symmetric])
  have b_sat: "b = sat (Until phi I psi) i"
  proof (rule iffI)
    assume b: "b"
    have mem: "mem (τ σ i) (τ σ (j' - Suc 0)) I"
      using b zo'_def tau_right_I[where ?k="j' - 1"]
      by (auto simp: mem_def b_def t_def zo'_Some split: nat.splits)
    have sat_psi: "sat psi (j' - 1)"
      using b zo'_def
      by (auto simp: b_def zo'_Some split: nat.splits)
    show "sat (Until phi I psi) i"
      using Suc_i_le_j' mem sat_psi sat_phi
      by (auto intro!: exI[of _ "j' - 1"])
  next
    assume "sat (Until phi I psi) i"
    then obtain k where k_def: "i k" "mem (τ σ i) (τ σ k) I" "sat psi k" "m {i..<k}. sat phi m"
      by auto
    define X where "X = {m {i..k}. memL (τ σ i) (τ σ m) I sat psi m}"
    have fin_X: "finite X" and X_nonempty: "X {}" and k_X: "k X"
      using k_def
      by (auto simp: X_def mem_def)
    define km where "km = Min X"
    note aux = Min_in[OF fin_X X_nonempty, folded km_def]
    have km_def: "i km" "km k" "memL (τ σ i) (τ σ km) I" "sat psi km" "m {i..<km}. sat phi m"
      "m {i..<km}. memL (τ σ i) (τ σ m) I ¬sat psi m"
      using aux Min_le[OF fin_X, folded km_def] k_def(4)
      by (fastforce simp: X_def)+
    have j'_le_km: "j' - 1 km"
      using not_sat_psi[OF _ km_def(3)] km_def(1,4)
      by fastforce
    show "b"
    proof (cases "j' - 1 < km")
      case True
      have "until_ready I t c' zo'"
        using end_cond True km_def(2) k_def(2) memR_mono'[OF _ τ_mono[where ?i=j' and ?j=k and ?s=σ]]
        by (auto simp: mem_def)
      then show ?thesis
        using c'_pos zo'_def km_def(5) Suc_i_le_j' True
        by (auto simp: until_ready_def zo'_Some b_def split: nat.splits)
    next
      case False
      have km_j': "km = j' - 1"
        using j'_le_km False
        by auto
      show ?thesis
        using c'_pos zo'_def km_def(3,4)
        by (auto simp: zo'_Some b_def km_j' t_def split: nat.splits)
    qed
  qed
  obtain gs where gs_def: "reaches_on ru_t l_t0 gs epsi'" "length gs = j'"
    "t. t set gs ==> memR (τ σ i) t I"
    using loop(1)
    by (auto simp: loop_inv_def j'_def[symmetric])
  note aux = τ_mono[where ?s=σ and ?i=i and ?j="Suc i"]
  have wf_v': "wf_vydra (Until phi I psi) (Suc i) (Suc n) v'"
    unfolding v'_def
    apply (rule wf_vydra.intros(10)[where ?j=j' and ?es'=gs])
    using loop(1) reaches_on_app[OF v_def(5) run_back] Suc_i_le_j' c'_j' memL_mono[OF _ aux] memR_mono[OF _ aux] gs_def
    by (auto simp: loop_inv_def j'_def[symmetric] v_def(6,8))
  show ?case
    using wf_v' ru_t_event[OF v_def(5) refl run_back]
    by (auto simp: b_sat v_def(6))
next
  case (MatchP n I r)
  have IH: "x set (collect_subfmlas r []) ==> wf_vydra x j n v ==> ru n v = Some (v', t, b) ==> wf_vydra x (Suc j) n v' t = τ σ j b = sat x j" for x j v v' t b
    using MatchP(2,1,5,6) le_trans[OF collect_subfmlas_msize]
    using bf_collect_subfmlas[where ?r="r" and ?phis="[]"]
    by (fastforce simp: collect_subfmlas_atms[where ?phis="[]", simplified, symmetric])
  have "reaches_on (ru n) (su n phi) vs v ==> wf_vydra phi (length vs) n v" if phi: "phi set (collect_subfmlas r [])" for phi vs v
    apply (induction vs arbitrary: v rule: rev_induct)
    using MatchP(1) wf_vydra_sub collect_subfmlas_msize[OF phi]
     apply (auto elim!: reaches_on.cases)[1]
    using IH[OF phi]
    apply (fastforce dest!: reaches_on_split_last)
    done
  then have wf: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) bs s ==> j < length (collect_subfmlas r []) ==>
    wf_vydra (collect_subfmlas r [] ! j) (length bs) n (s ! j)" for bs s j
    using reach_run_subs_run
    by (fastforce simp: in_set_conv_nth)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  define args where "args = init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  interpret MDL_window σ r l_t0 "map (su n) (collect_subfmlas r [])" args
    using bs_sat[where ?r=r and ?n=n, OF _ wf _ reach_run_subs_len[where ?n=n]] IH run_t_read[of run_hd]
      read_t_run[of _ _ run_hd] ru_t_tau MatchP(5) collect_subfmlas_atms[where ?phis="[]"]
    unfolding args_def iarray_of_list_def
    by unfold_locales auto
  obtain w xs where w_def: "v = VYDRA_MatchP I ?transs ?qf w"
    "valid_window_matchP args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w"
    using MatchP(3,4)
    by (auto simp: args_def elim!: wf_vydra.cases[of _ _ _ v])
  obtain tj' t' sj' bs where somes: "w_run_t args (w_tj w) = Some (tj', t')"
   "w_run_sub args (w_sj w) = Some (sj', bs)"
   using MatchP(4)
   by (auto simp: w_def(1) adv_end_def args_def Let_def split: option.splits prod.splits)
  obtain w' where w'_def"eval_mP I w = Some ((τ σ i, sat (MatchP I r) i), w')"
    "t' = τ σ i" "valid_matchP I l_t0 (map (su n) (collect_subfmlas r [])) (xs @ [(t', bs)]) (Suc i) w'"
    using valid_eval_matchP[OF w_def(2) somes] MatchP(6)
    by auto
  have v'_def"v' = VYDRA_MatchP I ?transs ?qf w'" "(t, b) = (τ σ i, sat (MatchP I r) i)"
    using MatchP(4)
    by (auto simp: w_def(1) args_def[symmetric] w'_def(1) simp del: eval_matchP.simps init_args.simps)
  have len_xs: "length xs = i"
    using w'_def(3)
    by (auto simp: valid_window_matchP_def)
  have "es e. reaches_on run_hd init_hd es e length es = Suc i"
    using ru_t_event valid_window_matchP_reach_tj[OF w_def(2)] somes(1) len_xs
    by (fastforce simp: args_def)
  then show ?case
    using MatchP(1) v'_def(2)  w'_def(3)
    by (auto simp: v'_def(1) args_def[symmetric] simp del: init_args.simps intro!: wf_vydra.intros(11))
next
  case (MatchF n I r)
  have IH: "x set (collect_subfmlas r []) ==> wf_vydra x j n v ==> ru n v = Some (v', t, b) ==> wf_vydra x (Suc j) n v' t = τ σ j b = sat x j" for x j v v' t b
    using MatchF(2,1,5,6) le_trans[OF collect_subfmlas_msize]
    using bf_collect_subfmlas[where ?r="r" and ?phis="[]"]
    by (fastforce simp: collect_subfmlas_atms[where ?phis="[]", simplified, symmetric])
  have "reaches_on (ru n) (su n phi) vs v ==> wf_vydra phi (length vs) n v" if phi: "phi set (collect_subfmlas r [])" for phi vs v
    apply (induction vs arbitrary: v rule: rev_induct)
    using MatchF(1) wf_vydra_sub collect_subfmlas_msize[OF phi]
     apply (auto elim!: reaches_on.cases)[1]
    using IH[OF phi]
    apply (fastforce dest!: reaches_on_split_last)
    done
  then have wf: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) bs s ==> j < length (collect_subfmlas r []) ==>
    wf_vydra (collect_subfmlas r [] ! j) (length bs) n (s ! j)" for bs s j
    using reach_run_subs_run
    by (fastforce simp: in_set_conv_nth)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  define args where "args = init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  interpret MDL_window σ r l_t0 "map (su n) (collect_subfmlas r [])" args
    using bs_sat[where ?r=r and ?n=n, OF _ wf _ reach_run_subs_len[where ?n=n]] IH run_t_read[of run_hd]
      read_t_run[of _ _ run_hd] ru_t_tau MatchF(5) collect_subfmlas_atms[where ?phis="[]"]
    unfolding args_def iarray_of_list_def
    by unfold_locales auto
  obtain w xs where w_def: "v = VYDRA_MatchF I ?transs ?qf w"
    "valid_window_matchF args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w"
    using MatchF(3,4)
    by (auto simp: args_def elim!: wf_vydra.cases[of _ _ _ v])
  obtain w' rho' where w'_def"eval_mF I w = Some ((t, b), w')" "valid_matchF I l_t0 (map (su n) (collect_subfmlas r [])) rho' (Suc i) w'" "t = τ σ i" "b = sat (MatchF I r) i"
    using valid_eval_matchF_sound[OF w_def(2)] MatchF(4,5,6)
    by (fastforce simp: w_def(1) args_def[symmetric] simp del: eval_matchF.simps init_args.simps split: option.splits)
  have v'_def"v' = VYDRA_MatchF I ?transs ?qf w'"
    using MatchF(4)
    by (auto simp: w_def(1) args_def[symmetric] w'_def(1) simp del: eval_matchF.simps init_args.simps)
  obtain w_ti' ti where ru_w_ti: "ru_t (w_ti w) = Some (w_ti', ti)"
    using MatchF(4) read_t_run
    by (auto simp: w_def(1) args_def split: option.splits)
  have "es e. reaches_on run_hd init_hd es e length es = Suc i"
    using w_def(2) ru_t_event[OF _ refl ru_w_ti, where ?ts="take (w_i w) (map fst xs)"]
    by (auto simp: valid_window_matchF_def args_def)
  then show ?case
    using MatchF(1) w'_def(2)
    by (auto simp: v'_def(1) args_def[symmetric] w'_def(3,4) simp del: init_args.simps intro!: wf_vydra.intros(12))
qed

lemma reaches_ons_run_lD: "reaches_on (run_subs (ru n)) vs ws vs' ==>
  length vs = length vs'"
  by (induction vs ws vs' rule: reaches_on_rev_induct)
     (auto simp: run_subs_def Let_def split: option.splits if_splits)

lemma reaches_ons_run_vD: "reaches_on (run_subs (ru n)) vs ws vs' ==>
  i < length vs ==> (ys. reaches_on (ru n) (vs ! i) ys (vs' ! i) length ys = length ws)"
proof (induction vs ws vs' rule: reaches_on_rev_induct)
  case (2 s s' bs bss s'')
  obtain ys where ys_def: "reaches_on (ru n) (s ! i) ys (s' ! i)"
    "length s = length s'" "length ys = length bss"
    using reaches_ons_run_lD[OF 2(1)] 2(3)[OF 2(4)]
    by auto
  obtain tb where tb_def: "ru n (s' ! i) = Some (s'' ! i, tb)"
    using run_subs_vD[OF 2(22(4)[unfolded ys_def(2)]]
    by auto
  show ?case
    using reaches_on_app[OF ys_def(1) tb_def(1)] ys_def(2,3) tb_def
    by auto
qed (auto intro: reaches_on.intros)

lemma reaches_ons_runI:
  assumes "phi. phi set (collect_subfmlas r []) ==> ws v. reaches_on (ru n) (su n phi) ws v length ws = i"
  shows "ws v. reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) ws v length ws = i"
  using assms
proof (induction i)
  case 0
  show ?case
    by (fastforce intro: reaches_on.intros)
next
  case (Suc i)
  have IH': "phi. phi set (collect_subfmlas r []) ==> ws v. reaches_on (ru n) (su n phi) ws v length ws = i ru n v None"
  proof -
    fix phi
    assume lassm: "phi set (collect_subfmlas r [])"
    obtain ws v where ws_def: "reaches_on (ru n) (su n phi) ws v"
      "length ws = Suc i"
      using Suc(2)[OF lassm]
      by auto
    obtain y ys where ws_snoc: "ws = ys @ [y]"
      using ws_def(2)
      by (cases ws rule: rev_cases) auto
    show "ws v. reaches_on (ru n) (su n phi) ws v length ws = i ru n v None"
      using reaches_on_split_last[OF ws_def(1)[unfolded ws_snoc]] ws_def(2) ws_snoc
      by fastforce
  qed
  obtain ws v where ws_def: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) ws v" "length ws = i"
    using Suc(1) IH'
    by blast
  have "x set v ==> Option.is_none (ru n x) ==> False" for x
    using ws_def IH'
    by (auto simp: in_set_conv_nth) (metis is_none_code(2) reach_run_subs_len reach_run_subs_run reaches_on_inj)
  then obtain v' tb where v'_def"run_subs (ru n) v = Some (v', tb)"
    by (fastforce simp: run_subs_def Let_def)
  show ?case
    using reaches_on_app[OF ws_def(1) v'_def] ws_def(2)
    by fastforce
qed

lemma reaches_on_takeWhile: "reaches_on r s vs s' ==> r s' = Some (s'', v) ==> ¬f v ==>
  vs' = takeWhile f vs ==>
  t' t'' v'. reaches_on r s vs' t' r t' = Some (t'', v') ¬f v'
  reaches_on r t' (drop (length vs') vs) s'"
  by (induction s vs s' arbitrary: vs' rule: reaches_on.induct) (auto intro: reaches_on.intros)

lemma reaches_on_suffix:
  assumes "reaches_on r s vs s'" "reaches_on r s vs' s''" "length vs' length vs"
  shows "vs''. reaches_on r s'' vs'' s' vs = vs' @ vs''"
  using reaches_on_split'[where ?i="length vs'", OF assms(1,3)] assms(3) reaches_on_inj[OF assms(2)]
  by (metis add_diff_cancel_right' append_take_drop_id diff_diff_cancel length_append length_drop)

lemma vydra_wf_reaches_on:
  assumes "j v. j < i ==> wf_vydra φ j n v ==> ru n v = None ==> False" "bounded_future_fmla φ" "wf_fmla φ" "msize_fmla φ n"
  shows "vs v. reaches_on (ru n) (su n φ) vs v wf_vydra φ i n v length vs = i"
  using assms(1)
proof (induction i)
  case (Suc i)
  obtain vs v where IH: "reaches_on (ru n) (su n φ) vs v" "wf_vydra φ i n v" "length vs = i"
    using Suc(1) Suc(2)[OF less_SucI]
    by auto
  show ?case
    using reaches_on_app[OF IH(1)] Suc(2)[OF _ IH(2)] vydra_sound_aux[OF assms(4) IH(2) _ assms(2,3)] IH(3)
    by fastforce
qed (auto intro: reaches_on.intros wf_vydra_sub[OF assms(4)])

lemma reaches_on_Some:
  assumes "reaches_on r s vs s'" "reaches_on r s vs' s''" "length vs < length vs'"
  shows "s''' x. r s' = Some (s''', x)"
  using reaches_on_split[OF assms(2,3)] reaches_on_inj[OF assms(1)] assms(3)
  by auto

lemma reaches_on_progress:
  assumes "reaches_on run_hd init_hd vs e"
  shows "progress phi (map fst vs) length vs"
  using progress_le_ts[of "map fst vs" phi] reaches_on_run_hd τ_fin
  by (fastforce dest!: reaches_on_setD[OF assms] reaches_on_split_last)

lemma vydra_complete_aux:
  assumes prefix: "reaches_on run_hd init_hd vs e"
    and run: "wf_vydra φ i n v" "ru n v = None" "i < progress φ (map fst vs)" "bounded_future_fmla φ" "wf_fmla φ"
    and msize: "msize_fmla φ n"
  shows "False"
  using msize run
proof (induction n φ arbitrary: i v rule: run_induct)
  case (Bool b n)
  have False if v_def: "v = VYDRA_Bool b g" for g
  proof -
    obtain es where g_def: "reaches_on run_hd init_hd es g" "length es = i"
      using Bool(1)
      by (auto simp: v_def elim: wf_vydra.cases)
    show False
      using Bool(2) reaches_on_Some[OF g_def(1) prefix] Bool(3)
      by (auto simp: v_def g_def(2) split: option.splits)
  qed
  then show False
    using Bool(1)
    by (auto elim!: wf_vydra.cases[of _ _ _ v])
next
  case (Atom a n)
  have False if v_def: "v = VYDRA_Atom a g" for g
  proof -
    obtain es where g_def: "reaches_on run_hd init_hd es g" "length es = i"
      using Atom(1)
      by (auto simp: v_def elim: wf_vydra.cases)
    show False
      using Atom(2) reaches_on_Some[OF g_def(1) prefix] Atom(3)
      by (auto simp: v_def g_def(2) split: option.splits)
  qed
  then show False
    using Atom(1)
    by (auto elim!: wf_vydra.cases[of _ _ _ v])
next
  case (Neg n phi)
  show ?case
    apply (rule wf_vydra.cases[OF Neg(3)])
    using Neg
    by (fastforce split: option.splits)+
next
  case (Bin n f phi psi)
  show ?case
    apply (rule wf_vydra.cases[OF Bin(4)])
    using Bin
    by (fastforce split: option.splits)+
next
  case (Prev n I phi)
  show ?case
  proof (cases i)
    case 0
    obtain vphi where v_def: "v = VYDRA_Prev I vphi init_hd None"
      using Prev(3)
      by (auto simp: 0 dest: reaches_on_NilD elim!: wf_vydra.cases[of "Prev I phi"])
    show ?thesis
      using Prev(4,5) prefix
      by (auto simp: 0 v_def elim: reaches_on.cases split: option.splits)
  next
    case (Suc j)
    show ?thesis
    proof (cases "v = VYDRA_None")
      case v_def: True
      obtain w where w_def: "wf_vydra phi j n w" "ru n w = None"
        using Prev(3)
        by (auto simp: Suc v_def elim!: wf_vydra.cases[of "Prev I phi"])
      show ?thesis
        using Prev(2)[OF w_def(1,2)] Prev(5,6,7)
        by (auto simp: Suc)
    next
      case False
      obtain vphi tphi bphi es g where v_def: "v = VYDRA_Prev I vphi g (Some (tphi, bphi))"
        "wf_vydra phi (Suc j) n vphi" "reaches_on run_hd init_hd es g" "length es = Suc j"
        using Prev(3) False
        by (auto simp: Suc elim!: wf_vydra.cases[of "Prev I phi"])
      show ?thesis
        using Prev(4,5) reaches_on_Some[OF v_def(3) prefix]
        by (auto simp: Let_def Suc v_def(1,4) split: option.splits)
    qed
  qed
next
  case (Next n I phi)
  show ?case
  proof (cases "v = VYDRA_None")
    case True
    obtain w where w_def: "wf_vydra phi i n w" "ru n w = None"
      using Next(3)
      by (auto simp: True elim: wf_vydra.cases)
    show ?thesis
      using Next(2)[OF w_def] Next(5,6,7)
      by (auto split: nat.splits)
  next
    case False
    obtain w sub to es where v_def: "v = VYDRA_Next I w sub to" "wf_vydra phi (length es) n w"
      "reaches_on run_hd init_hd es sub" "length es = (case to of None ==> 0 | _ ==> Suc i)"
      "case to of None ==> i = 0 | Some told ==> told = τ σ i"
      using Next(3) False
      by (auto elim!: wf_vydra.cases[of _ _ _ v] split: option.splits nat.splits)
    show ?thesis
    proof (cases to)
      case None
      obtain w' tw' bw' where w'_def"ru n w = Some (w', (tw', bw'))"
        using Next(2)[OF v_def(2)] Next(5,6,7)
        by (fastforce simp: v_def(4) None split: nat.splits)
      have wf: "wf_vydra phi (Suc (length es)) n w'"
        using v_def(4,5) vydra_sound_aux[OF Next(1) v_def(2) w'_defNext(6,7)
        by (auto simp: None)
      show ?thesis
        using Next(2)[OF wf] Next(4,5,6,7) reaches_on_Some[OF v_def(3) prefix]
          reaches_on_Some[OF reaches_on_app[OF v_def(3)] prefix] reaches_on_progress[OF prefix, where ?phi=phi]
        by (cases vs) (fastforce simp: v_def(1,4) w'_def None split: option.splits nat.splits if_splits)+
    next
      case (Some z)
      show ?thesis
        using Next(2)[OF v_def(2)] Next(4,5,6,7) reaches_on_Some[OF v_def(3) prefix] reaches_on_progress[OF prefix, where ?phi=phi]
        by (auto simp: v_def(1,4) Some split: option.splits nat.splits)
    qed
  qed
next
  case (Since n I phi psi)
  obtain vphi vpsi g cphi cpsi cppsi tppsi j gs where v_def:
    "v = VYDRA_Since I vphi vpsi g cphi cpsi cppsi tppsi"
    "wf_vydra phi i n vphi" "wf_vydra psi j n vpsi" "j i"
    "reaches_on ru_t l_t0 gs g" "length gs = j" "cpsi = i - j"
    using Since(5)
    by (auto elim: wf_vydra.cases)
  obtain vphi' t1 b1 where run_vphi: "ru n vphi = Some (vphi', t1, b1)"
    using Since(3)[OF v_def(2)] Since(7,8,9)
    by fastforce
  obtain cs c where wf_vphi': "wf_vydra phi (Suc i) n vphi'"
    and reaches_Suc_i: "reaches_on run_hd init_hd cs c" "length cs = Suc i"
    and t1_def: "t1 = τ σ i"
    using vydra_sound_aux[OF Since(1) v_def(2) run_vphi] Since(8,9)
    by auto
  note ru_t_Some = ru_t_Some[OF reaches_Suc_i]
  define loop_inv where "loop_inv = (λ(vpsi, e, cpsi :: nat, cppsi :: nat option, tppsi :: 't option).
    let j = Suc i - cpsi in cpsi Suc i wf_vydra psi j n vpsi (es. reaches_on ru_t l_t0 es e length es = j))"
  define loop_init where "loop_init = (vpsi, g, Suc cpsi, map_option Suc cppsi, tppsi)"
  have j_def: "j = i - cpsi" and cpsi_i: "cpsi i"
    using v_def(4,7)
    by auto
  then have loop_inv_init: "loop_inv loop_init"
    using v_def(3,5,6,7) last_before_Some
    by (fastforce simp: loop_inv_def loop_init_def Let_def j_def split: option.splits)
  have wf_loop: "wf {(s', s). loop_inv s while_since_cond I t1 s Some s' = while_since_body run_hd (ru n) s}"
    by (auto intro: wf_subset[OF wf_since])
  have step_loop: "pred_option' loop_inv (while_since_body run_hd (ru n) s)"
    if loop_assms: "loop_inv s" "while_since_cond I t1 s" for s
  proof -
    obtain vpsi d cpsi cppsi tppsi where s_def: "s = (vpsi, d, cpsi, cppsi, tppsi)"
      by (cases s) auto
    have cpsi_pos: "cpsi > 0"
      using loop_assms(2)
      by (auto simp: while_since_cond_def s_def)
    define j where "j = Suc i - cpsi"
    have j_i: "j i"
      using cpsi_pos
      by (auto simp: j_def)
    obtain ds where loop_before: "cpsi Suc i" "wf_vydra psi j n vpsi" "reaches_on ru_t l_t0 ds d" "length ds = j"
      using loop_assms(1)
      by (auto simp: s_def j_def loop_inv_def Let_def)
    obtain h tt where tt_def: "read_t d = Some tt" "d = Some (h, tt)"
      using ru_t_Some[OF loop_before(3)] loop_before(4) loop_assms(2)
      by (cases d) (fastforce simp: while_since_cond_def s_def j_def split: option.splits)+
    obtain d' where d'_def"reaches_on ru_t l_t0 (ds @ [tt]) d'" "ru_t d = Some (d', tt)"
      using reaches_on_app[OF loop_before(3)] tt_def(1)
      by (cases "run_hd h") (auto simp: tt_def(2))
    obtain vpsi' tpsi' bpsi' where run_vpsi: "ru n vpsi = Some (vpsi', (tpsi', bpsi'))"
      using Since(4) j_i Since(7,8,9) loop_before(2)
      by fastforce
    have wf_psi': "wf_vydra psi (Suc j) n vpsi'" and t'_def"tpsi' = τ σ j" and b'_def"bpsi' = sat psi j"
      using vydra_sound_aux[OF Since(2) loop_before(2) run_vpsi] Since(8,9)
      by auto
    define j' where j'_def"j' = Suc i - (cpsi - Suc 0)"
    have j'_j: "j' = Suc j"
      using loop_before(1) cpsi_pos
      by (auto simp: j'_def j_def)
    show ?thesis
      using wf_psi'(1) loop_before(1,4) d'_def(1)
      by (fastforce simp: while_since_body_def s_def run_vpsi pred_option'_def loop_inv_def j'_def[symmetric] j'_j d'_def(2) t1_def)
  qed
  show ?case
    using while_break_complete[OF step_loop _ wf_loop loop_inv_init, where ?Q="λ_. True"] Since(6)
    by (auto simp: pred_option'_def v_def(1) run_vphi Let_def loop_init_def split: option.splits)
next
  case (Until n I phi psi)
  obtain "back" vphi vpsi front c z es es' j where v_def:
    "v = VYDRA_Until I back vphi vpsi front c z"
    "wf_vydra phi j n vphi" "wf_vydra psi j n vpsi" "i j"
    "reaches_on ru_t l_t0 es back" "length es = i"
    "reaches_on ru_t l_t0 es' front" "length es' = j" "t. t set es' ==> memR (τ σ i) t I"
    "c = j - i" "z = (case j of 0 ==> None | Suc k ==> Some (τ σ k, sat phi k, sat psi k))"
    "k. k {i..<j - 1} ==> sat phi k (memL (τ σ i) (τ σ k) I ¬sat psi k)"
    using Until(5)
    by (auto simp: elim: wf_vydra.cases)
  have ru_t_Some: "reaches_on ru_t l_t0 gs g ==> length gs < length vs ==> g' gt. ru_t g = Some (g', gt)" for gs g
    using reaches_on_Some reaches_on_run_hd_t[OF prefix]
    by fastforce
  have vs_tau: "map fst vs ! k = τ σ k" if k_vs: "k < length vs" for k
    using reaches_on_split[OF prefix k_vs] run_hd_sound k_vs
    apply (cases "vs ! k")
    apply (auto)
    apply (metis fst_conv length_map nth_map prefix reaches_on_run_hd_t ru_t_tau_in)
    done
  define m where "m = min (length (map fst vs) - 1) (min (progress phi (map fst vs)) (progress psi (map fst vs)))"
  have m_vs: "m < length vs"
    using Until(7)
    by (cases vs) (auto simp: m_def split: if_splits)
  define A where "A = {j. 0 j j m memR (map fst vs ! j) (map fst vs ! m) I}"
  have m_A: "m A"
    using memR_tfin_refl[OF τ_fin] vs_tau[OF m_vs]
    by (fastforce simp: A_def)
  then have A_nonempty: "A {}"
    by auto
  have A_finite: "finite A"
    by (auto simp: A_def)
  have p: "progress (Until phi I psi) (map fst vs) = Min A"
    using Until(7)
    unfolding progress.simps m_def[symmetric] Let_def A_def[symmetric]
    by auto
  have i_A: "i A"
    using Until(7) A_finite A_nonempty
    by (auto simp del: progress.simps simp: p)
  have i_m: "i < m"
    using Until(7) m_A A_finite A_nonempty
    by (auto simp del: progress.simps simp: p)
  have memR_i_m: "¬memR (map fst vs ! i) (map fst vs ! m) I"
    using i_A i_m
    by (auto simp: A_def)
  have i_vs: "i < length vs"
    using i_m m_vs
    by auto
  have j_m: "j m"
    using ru_t_tau_in[OF v_def(7), of m] v_def(9)[of "τ σ m"] memR_i_m
    unfolding vs_tau[OF i_vs] vs_tau[OF m_vs]
    by (force simp: in_set_conv_nth v_def(8))
  have j_vs: "j < length vs"
    using j_m m_vs
    by auto
  obtain back' t where run_back: "ru_t back = Some (back', t)" and t_def: "t = τ σ i"
    using ru_t_Some[OF v_def(5)] v_def(4) j_vs ru_t_tau[OF v_def(5)]
    by (fastforce simp: v_def(6))
  define loop_inv where "loop_inv = (λ(vphi, vpsi, front, c, z :: ('t × bool × bool) option).
    let j = i + c in wf_vydra phi j n vphi wf_vydra psi j n vpsi j < length vs
    (es'. reaches_on ru_t l_t0 es' front length es' = j)
    (z = None j = 0))"
  define loop_init where "loop_init = (vphi, vpsi, front, c, z)"
  have j_eq: "j = i + c"
    using v_def(4)
    by (auto simp: v_def(10))
  have "j = 0 ==> c = 0"
    by (auto simp: j_eq)
  then have loop_inv_init: "loop_inv loop_init"
    using v_def(2,3,4,7,8,9,11) j_vs
    by (auto simp: loop_inv_def loop_init_def j_eq[symmetric] split: nat.splits)
  have loop_step: "pred_option' loop_inv (while_until_body run_hd (ru n) s)" if loop_assms: "loop_inv s" "while_until_cond I t s" for s
  proof -
    obtain vphi_cur vpsi_cur epsi_cur c_cur zo_cur where s_def: "s = (vphi_cur, vpsi_cur, epsi_cur, c_cur, zo_cur)"
      by (cases s) auto
    define j_cur where "j_cur = i + c_cur"
    obtain gs where wf: "wf_vydra phi j_cur n vphi_cur" "wf_vydra psi j_cur n vpsi_cur"
      and gs_def: "reaches_on ru_t l_t0 gs epsi_cur" "length gs = j_cur"
      and j_cur_vs: "j_cur < length vs"
      using loop_assms(1)
      by (auto simp: loop_inv_def s_def j_cur_def[symmetric])
    obtain epsi'_cur t'_cur where run_epsi: "ru_t epsi_cur = Some (epsi'_cur, t'_cur)"
      and t'_cur_def: "t'_cur = τ σ (length gs)"
      using ru_t_Some[OF gs_def(1)] ru_t_event[OF gs_def(1) refl] j_cur_vs
      by (auto simp: gs_def(2))
    have j_m: "j_cur < m"
      using loop_assms(2) memR_i_m memR_mono'[OF _ τ_mono, of _ _ _ _ m]
      unfolding vs_tau[OF i_vs] vs_tau[OF m_vs]
      by (fastforce simp: gs_def(2) while_until_cond_def s_def run_t_read[OF run_epsi] t_def t'_cur_def)
    have j_cur_prog_phi: "j_cur < progress phi (map fst vs)"
      using j_m
      by (auto simp: m_def)
    have j_cur_prog_psi: "j_cur < progress psi (map fst vs)"
      using j_m
      by (auto simp: m_def)
    obtain vphi'_cur tphi_cur bphi_cur where run_vphi: "ru n vphi_cur = Some (vphi'_cur, (tphi_cur, bphi_cur))"
      using Until(3)[OF wf(1) _ j_cur_prog_phi] Until(8,9)
      by fastforce
    obtain vpsi'_cur tpsi_cur bpsi_cur where run_vpsi: "ru n vpsi_cur = Some (vpsi'_cur, (tpsi_cur, bpsi_cur))"
      using Until(4)[OF wf(2) _ j_cur_prog_psi] Until(8,9)
      by fastforce
    have wf': "wf_vydra phi (Suc j_cur) n vphi'_cur" "wf_vydra psi (Suc j_cur) n vpsi'_cur"
      using vydra_sound_aux[OF Until(1) wf(1) run_vphi] vydra_sound_aux[OF Until(2) wf(2) run_vpsi] Until(8,9)
      by auto
    show ?thesis
      using wf' reaches_on_app[OF gs_def(1) run_epsi] gs_def(2) j_m m_vs
      by (auto simp: pred_option'_def while_until_body_def s_def run_epsi run_vphi run_vpsi loop_inv_def j_cur_def[symmetric])
  qed
  have wf_loop: "wf {(s', s). loop_inv s while_until_cond I t s Some s' = while_until_body run_hd (ru n) s}"
  proof -
    obtain m where m_def: "¬τ σ m τ σ i + right I"
      using ex_lt_τ[where ?x="right I" and ?s=σ] Until(8)
      by auto
    define X where "X = {(s', s). loop_inv s while_until_cond I t s Some s' = while_until_body run_hd (ru n) s}"
    have "memR t (τ σ (i + c)) I ==> i + c < m" for c
      using m_def order_trans[OF τ_mono[where ?i=m and ?j="i + c" and ?s=σ]]
      by (fastforce simp: t_def dest!: memR_dest)
    then have "X measure (λ(vphi, vpsi, epsi, c, zo). m - c)"
      by (fastforce simp: X_def while_until_cond_def while_until_body_def loop_inv_def Let_def split: option.splits
          dest!: read_t_run[where ?run_hd=run_hd] dest: ru_t_tau)
    then show ?thesis
      using wf_subset
      by (auto simp: X_def[symmetric])
  qed
  obtain vphi' vpsi' front' c' z' where loop:
    "while_break (while_until_cond I t) (while_until_body run_hd (ru n)) loop_init = Some (vphi', vpsi', front', c', z')"
    "loop_inv (vphi', vpsi', front', c', z')" "¬while_until_cond I t (vphi', vpsi', front', c', z')"
    using while_break_complete[where ?P="loop_inv", OF loop_step _ wf_loop loop_inv_init]
    by (cases "while_break (while_until_cond I t) (while_until_body run_hd (ru n)) loop_init") (force simp: pred_option'_def)+
  define j' where "j' = i + c'"
  obtain tf where read_front': "read_t front' = Some tf"
    using loop(2)
    by (auto simp: loop_inv_def j'_def[symmetric] dest!: ru_t_Some run_t_read[where ?run_hd=run_hd])
  have tf_fin: "tf tfin"
    using loop(2) ru_t_Some[where ?g=front'] ru_t_tau[where ?t'=front'] read_t_run[OF read_front'] τ_fin[where ?σ=σ]
    by (fastforce simp: loop_inv_def j'_def[symmetric])
  have c'_pos: "c' = 0 ==> False"
    using loop(2,3) ru_t_tau ru_t_tau[OF reaches_on.intros(1)] read_t_run[OF read_front']
      memR_tfin_refl[OF tf_fin]
    by (fastforce simp: loop_inv_def while_until_cond_def until_ready_def read_front' t_def dest!: reaches_on_NilD)
  have z'_Some: "z' = None ==> False"
    using loop(2) c'_pos
    by (auto simp: loop_inv_def j'_def[symmetric])
  show ?case
    using Until(6) c'_pos z'_Some
    by (auto simp: v_def(1) run_back loop_init_def[symmetric] loop(1) read_front' split: if_splits option.splits)
next
  case (MatchP n I r)
  have msize_sub: "x. x set (collect_subfmlas r []) ==> msize_fmla x n"
    using le_trans[OF collect_subfmlas_msize] MatchP(1)
    by auto
  have sound: "x set (collect_subfmlas r []) ==> wf_vydra x j n v ==> ru n v = Some (v', t, b) ==> wf_vydra x (Suc j) n v' t = τ σ j b = sat x j" for x j v v' t b
    using MatchP vydra_sound_aux[OF msize_sub] le_trans[OF collect_subfmlas_msize]
    using bf_collect_subfmlas[where ?r="r" and ?phis="[]"]
    by (fastforce simp: collect_subfmlas_atms[where ?phis="[]", simplified, symmetric])
  have "reaches_on (ru n) (su n phi) vs v ==> wf_vydra phi (length vs) n v" if phi: "phi set (collect_subfmlas r [])" for phi vs v
    apply (induction vs arbitrary: v rule: rev_induct)
    using MatchP(1) wf_vydra_sub collect_subfmlas_msize[OF phi]
     apply (auto elim!: reaches_on.cases)[1]
    using sound[OF phi]
    apply (fastforce dest!: reaches_on_split_last)
    done
  then have wf: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) bs s ==> j < length (collect_subfmlas r []) ==>
    wf_vydra (collect_subfmlas r [] ! j) (length bs) n (s ! j)" for bs s j
    using reach_run_subs_run
    by (fastforce simp: in_set_conv_nth)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  define args where "args = init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  interpret MDL_window σ r l_t0 "map (su n) (collect_subfmlas r [])" args
    using bs_sat[where ?r=r and ?n=n, OF _ wf _ reach_run_subs_len[where ?n=n]] sound run_t_read[of run_hd]
      read_t_run[of _ _ run_hd] ru_t_tau MatchP(5) collect_subfmlas_atms[where ?phis="[]"]
    unfolding args_def iarray_of_list_def
    by unfold_locales auto
  obtain w xs where w_def: "v = VYDRA_MatchP I ?transs ?qf w"
    "valid_window_matchP args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w"
    using MatchP(3)
    by (auto simp: args_def elim!: wf_vydra.cases)
  note args' = args_def[unfolded init_args.simps, symmetric]
  have run_args: "w_run_t args = ru_t" "w_run_sub args = run_subs (ru n)"
    by (auto simp: args_def)
  have len_xs: "length xs = i"
    using w_def(2)
    by (auto simp: valid_window_matchP_def)
  obtain ej tj where w_tj: "ru_t (w_tj w) = Some (ej, tj)"
    using reaches_on_Some[OF valid_window_matchP_reach_tj[OF w_def(2)]] reaches_on_run_hd_t[OF prefix]
      MatchP(5) reaches_on_progress[OF prefix, where ?phi="MatchP I r"]
    by (fastforce simp: run_args len_xs simp del: progress.simps)
  have "run_subs (ru n) (w_sj w) = None"
    using valid_eval_matchP[OF w_def(2), unfolded run_args] w_tj MatchP(4,7)
    by (cases "run_subs (ru n) (w_sj w)") (auto simp: w_def(1) args' simp del: eval_matchP.simps split: option.splits)
  then obtain j where j_def: "j < length (w_sj w)" "ru n (w_sj w ! j) = None"
    by (auto simp: run_subs_def Let_def in_set_conv_nth Option.is_none_def split: if_splits)
  have len_w_sj: "length (w_sj w) = length (collect_subfmlas r [])"
    using valid_window_matchP_reach_sj[OF w_def(2)] reach_run_subs_len
    by (auto simp: run_args)
  define phi where "phi = collect_subfmlas r [] ! j"
  have phi_in_set: "phi set (collect_subfmlas r [])"
    using j_def(1)
    by (auto simp: phi_def in_set_conv_nth len_w_sj)
  have wf: "wf_vydra phi i n (w_sj w ! j)"
    using valid_window_matchP_reach_sj[OF w_def(2)] wf[folded len_w_sj, OF _ j_def(1)] len_xs
    by (fastforce simp: run_args phi_def)
  have "i < progress phi (map fst vs)"
    using MatchP(5) phi_in_set atms_nonempty[of r] atms_finite[of r] collect_subfmlas_atms[of r "[]"]
    by auto
  then show ?case
    using MatchP(2)[OF msize_sub[OF phi_in_set] wf j_def(2)] MatchP(6,7) phi_in_set
      bf_collect_subfmlas[where ?r="r" and ?phis="[]"]
    by (auto simp: collect_subfmlas_atms)
next
  case (MatchF n I r)
  have subfmla: "msize_fmla x n" "bounded_future_fmla x" "wf_fmla x" if "x set (collect_subfmlas r [])" for x
    using that MatchF(1,6,7) le_trans[OF collect_subfmlas_msize] bf_collect_subfmlas[where ?r="r" and ?phis="[]" and ?phi=x]
      collect_subfmlas_atms[where ?phis="[]" and ?r=r]
    by auto
  have sound: "x set (collect_subfmlas r []) ==> wf_vydra x j n v ==> ru n v = Some (v', t, b) ==> wf_vydra x (Suc j) n v' t = τ σ j b = sat x j" for x j v v' t b
    using MatchF vydra_sound_aux subfmla
    by fastforce
  have "reaches_on (ru n) (su n phi) vs v ==> wf_vydra phi (length vs) n v" if phi: "phi set (collect_subfmlas r [])" for phi vs v
    apply (induction vs arbitrary: v rule: rev_induct)
    using MatchF(1) wf_vydra_sub subfmla(1)[OF phi] sound[OF phi]
     apply (auto elim!: reaches_on.cases)[1]
    using sound[OF phi]
    apply (fastforce dest!: reaches_on_split_last)
    done
  then have wf: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) bs s ==> j < length (collect_subfmlas r []) ==>
    wf_vydra (collect_subfmlas r [] ! j) (length bs) n (s ! j)" for bs s j
    using reach_run_subs_run
    by (fastforce simp: in_set_conv_nth)
  let ?qf = "state_cnt r"
  let ?transs = "iarray_of_list (build_nfa_impl r (0, ?qf, []))"
  define args where "args = init_args ({0}, NFA.delta' ?transs ?qf, NFA.accept' ?transs ?qf) (ru_t, read_t) (run_subs (ru n))"
  interpret MDL_window σ r l_t0 "map (su n) (collect_subfmlas r [])" args
    using bs_sat[where ?r=r and ?n=n, OF _ wf _ reach_run_subs_len[where ?n=n]] sound run_t_read[of run_hd]
      read_t_run[of _ _ run_hd] ru_t_tau MatchF(5) subfmla
    unfolding args_def iarray_of_list_def
    by unfold_locales auto
  obtain w xs where w_def: "v = VYDRA_MatchF I ?transs ?qf w"
    "valid_window_matchF args I l_t0 (map (su n) (collect_subfmlas r [])) xs i w"
    using MatchF(3)
    by (auto simp: args_def elim!: wf_vydra.cases)
  note args' = args_def[unfolded init_args.simps, symmetric]
  have run_args: "w_run_t args = ru_t" "w_read_t args = read_t" "w_run_sub args = run_subs (ru n)"
    by (auto simp: args_def)
  have vs_tau: "map fst vs ! k = τ σ k" if k_vs: "k < length vs" for k
    using reaches_on_split[OF prefix k_vs] run_hd_sound k_vs
    apply (cases "vs ! k")
    apply (auto)
    apply (metis fst_conv length_map nth_map prefix reaches_on_run_hd_t ru_t_tau_in)
    done
  define m where "m = min (length (map fst vs) - 1) (Min ((λf. progress f (map fst vs)) ` atms r))"
  have m_vs: "m < length vs"
    using MatchF(5)
    by (cases vs) (auto simp: m_def split: if_splits)
  define A where "A = {j. 0 j j m memR (map fst vs ! j) (map fst vs ! m) I}"
  have m_A: "m A"
    using memR_tfin_refl[OF τ_fin] vs_tau[OF m_vs]
    by (fastforce simp: A_def)
  then have A_nonempty: "A {}"
    by auto
  have A_finite: "finite A"
    by (auto simp: A_def)
  have p: "progress (MatchF I r) (map fst vs) = Min A"
    using MatchF(5)
    unfolding progress.simps m_def[symmetric] Let_def A_def[symmetric]
    by auto
  have i_A: "i A"
    using MatchF(5) A_finite A_nonempty
    by (auto simp del: progress.simps simp: p)
  have i_m: "i < m"
    using MatchF(5) m_A A_finite A_nonempty
    by (auto simp del: progress.simps simp: p)
  have memR_i_m: "¬memR (map fst vs ! i) (map fst vs ! m) I"
    using i_A i_m
    by (auto simp: A_def)
  have i_vs: "i < length vs"
    using i_m m_vs
    by auto
  obtain ti where read_ti: "w_read_t args (w_ti w) = Some ti"
    using w_def(2) reaches_on_Some[where ?r=ru_t and ?s=l_t0 and ?s'="w_ti w"]
      reaches_on_run_hd_t[OF prefix] i_vs run_t_read[where ?t="w_ti w"]
    by (fastforce simp: valid_window_matchF_def run_args)
  have ti_def: "ti = τ σ i"
    using w_def(2) ru_t_tau read_t_run[OF read_ti]
    by (fastforce simp: valid_window_matchF_def run_args)
  note reach_tj = valid_window_matchF_reach_tj[OF w_def(2), unfolded run_args]
  note reach_sj = valid_window_matchF_reach_sj[OF w_def(2), unfolded run_args]
  have len_xs: "length xs = w_j w" and memR_xs: "l. l{w_i w..<w_j w} ==> memR (ts_at xs i) (ts_at xs l) I"
    and i_def: "w_i w = i"
    using w_def(2)
    unfolding valid_window_matchF_def
    by (auto simp: valid_window_matchF_def run_args)
  have j_m: "w_j w m"
    using ru_t_tau_in[OF reach_tj, of i] ru_t_tau_in[OF reach_tj, of m] memR_i_m i_m memR_xs[of m]
    unfolding vs_tau[OF i_vs] vs_tau[OF m_vs]
    by (force simp: in_set_conv_nth len_xs ts_at_def i_def)
  obtain tm tm' where tm_def: "reaches_on ru_t l_t0 (take m (map fst vs)) tm"
    "ru_t tm = Some (tm', fst (vs ! m))"
    using reaches_on_split[where ?i=m] reaches_on_run_hd_t[OF prefix] m_vs
    by fastforce
  have reach_tj_m: "reaches_on (w_run_t args) (w_tj w) (drop (w_j w) (take m (map fst vs))) tm"
    using reaches_on_split'[OF tm_def(1), where ?i="w_j w"] reaches_on_inj[OF reach_tj] m_vs j_m
    by (auto simp: len_xs run_args)
  have vs_m: "fst (vs ! m) = τ σ m"
    using vs_tau[OF m_vs] m_vs
    by auto
  have memR_ti_m: "¬memR ti (τ σ m) I"
    using memR_i_m
    unfolding vs_tau[OF i_vs] vs_tau[OF m_vs]
    by (auto simp: ti_def)
  have m_prog: "m progress phi (map fst vs)" if "phi set (collect_subfmlas r [])" for phi
    using collect_subfmlas_atms[where ?r=r and ?phis="[]"] that atms_finite[of r]
    by (auto simp: m_def min.coboundedI2)
  obtain ws s where ws_def: "reaches_on (run_subs (ru n)) (map (su n) (collect_subfmlas r [])) ws s" "length ws = m"
    using reaches_ons_runI[where ?r=r and ?n=n and ?i=m]
      vydra_wf_reaches_on[where ?i=m and ?n=n] subfmla
      MatchF(2) m_prog
    by fastforce
  have reach_sj_m: "reaches_on (run_subs (ru n)) (w_sj w) (drop (w_j w) ws) s"
    using reaches_on_split'[OF ws_def(1), where ?i="w_j w"] reaches_on_inj[OF reach_sj] i_m j_m
    by (auto simp: ws_def(2) len_xs)
  define rho where "rho = zip (drop (w_j w) (take m (map fst vs))) (drop (w_j w) ws)"
  have map_fst_rho: "map fst rho = drop (w_j w) (take m (map fst vs))"
    and map_snd_rho: "map snd rho = drop (w_j w) ws"
    using ws_def(2) j_m m_vs
    by (auto simp: rho_def)
  show False
    using valid_eval_matchF_complete[OF w_def(2) reach_tj_m[folded map_fst_rho] reach_sj_m[folded map_snd_rho run_args] read_ti run_t_read[OF tm_def(2)[folded run_args], unfolded vs_m] memR_ti_m] MatchF(4,7)
    by (auto simp: w_def(1) args_def simp del: eval_matchF.simps)
qed

definition "ru' φ = ru (msize_fmla φ)"
definition "su' φ = su (msize_fmla φ) φ"

lemma vydra_wf:
  assumes "reaches (ru n) (su n φ) i v" "bounded_future_fmla φ" "wf_fmla φ" "msize_fmla φ n"
  shows "wf_vydra φ i n v"
  using assms(1)
proof (induction i arbitrary: v)
  case 0
  then show ?case
    using wf_vydra_sub[OF assms(4)]
    by (auto elim: reaches.cases)
next
  case (Suc i)
  show ?case
    using reaches_Suc_split_last[OF Suc(2)] Suc(1) vydra_sound_aux[OF assms(4) _ _ assms(2,3)]
    by fastforce
qed

lemma vydra_sound':
  assumes "reaches (ru' φ) (su' φ) n v" "ru' φ v = Some (v', (t, b))" "bounded_future_fmla φ" "wf_fmla φ"
  shows "(t, b) = (τ σ n, sat φ n)"
  using vydra_sound_aux[OF order.refl vydra_wf[OF assms(1)[unfolded ru'_def su'_def] assms(3,4) order.refl] assms(2)[unfolded ru'_def] assms(3,4)]
  by auto

lemma vydra_complete':
  assumes prefix: "reaches_on run_hd init_hd vs e"
    and prog: "n < progress φ (map fst vs)" "bounded_future_fmla φ" "wf_fmla φ"
  shows "v v'. reaches (ru' φ) (su' φ) n v ru' φ v = Some (v', (τ σ n, sat φ n))"
proof -
  have aux: "False" if aux_assms: "j n" "wf_vydra φ j (msize_fmla φ) v" "ru (msize_fmla φ) v = None" for j v
    using vydra_complete_aux[OF prefix aux_assms(2,3) _ prog(2-)] aux_assms(1) prog(1)
    by auto
  obtain ws v where ws_def: "reaches_on (ru' φ) (su' φ) ws v" "wf_vydra φ n (msize_fmla φ) v" "length ws = n"
    using vydra_wf_reaches_on[OF _ prog(2,3)] aux[OF less_imp_le_nat]
    unfolding ru'_def su'_def
    by blast
  have ru_Some: "ru' φ v None"
    using aux[OF order.refl ws_def(2)]
    by (fastforce simp: ru'_def)
  obtain v' t b where tb_def: "ru' φ v = Some (v', (t, b))"
    using ru_Some
    by auto
  show ?thesis
    using reaches_on_n[OF ws_def(1)] tb_def vydra_sound'[OF reaches_on_n[OF ws_def(1)] tb_def prog(2,3)]
    by (auto simp: ws_def(3))
qed

lemma map_option_apfst_idle: "map_option (apfst snd) (map_option (apfst (Pair n)) x) = x"
  by (cases x) auto

lemma vydra_sound:
  assumes "reaches (run_vydra run_hd) (init_vydra init_hd run_hd φ) n v" "run_vydra run_hd v = Some (v', (t, b))" "bounded_future_fmla φ" "wf_fmla φ"
  shows "(t, b) = (τ σ n, sat φ n)"
proof -
  have fst_v: "fst v = msize_fmla φ"
    by (rule reaches_invar[OF assms(1)]) (auto simp: init_vydra_def run_vydra_def Let_def)
  have "reaches (ru' φ) (su' φ) n (snd v)"
    using reaches_cong[OF assms(1), where ?P="λ(m, w). m = msize_fmla φ" and ?g=snd]
    by (auto simp: init_vydra_def run_vydra_def ru'_def su'_def map_option_apfst_idle Let_def simp del: sub.simps)
  then show ?thesis
    using vydra_sound'[OF _ _ assms(3,4)] assms(2) fst_v
    by (auto simp: run_vydra_def ru'_def split: prod.splits)
qed

lemma vydra_complete:
  assumes prefix: "reaches_on run_hd init_hd vs e"
    and prog: "n < progress φ (map fst vs)" "bounded_future_fmla φ" "wf_fmla φ"
  shows "v v'. reaches (run_vydra run_hd) (init_vydra init_hd run_hd φ) n v run_vydra run_hd v = Some (v', (τ σ n, sat φ n))"
proof -
  obtain v v' where wits: "reaches (ru' φ) (su' φ) n v" "ru' φ v = Some (v', τ σ n, sat φ n)"
    using vydra_complete'[OF assms]
    by auto
  have reach: "reaches (run_vydra run_hd) (init_vydra init_hd run_hd φ) n (msize_fmla φ, v)"
    using reaches_cong[OF wits(1), where ?P="λx. True" and ?f'="run_vydra run_hd" and ?g="Pair (msize_fmla φ)"]
    by (auto simp: init_vydra_def run_vydra_def ru'_def su'_def Let_def simp del: sub.simps)
  show ?thesis
    apply (rule exI[of _ "(msize_fmla φ, v)"])
    apply (rule exI[of _ "(msize_fmla φ, v')"])
    apply (auto simp: run_vydra_def wits(2)[unfolded ru'_def] intro: reach)
    done
qed

end

context MDL
begin

lemma reach_elem:
  assumes "reaches (λi. if P i then Some (Suc i, (τ σ i, Γ σ i)) else None) s n s'" "s = 0"
  shows "s' = n"
proof -
  obtain vs where vs_def: "reaches_on (λi. if P i then Some (Suc i, (τ σ i, Γ σ i)) else None) s vs s'" "length vs = n"
    using reaches_on[OF assms(1)]
    by auto
  have "s' = length vs"
    using vs_def(1) assms(2)
    by (induction s vs s' rule: reaches_on_rev_induct) (auto split: if_splits)
  then show ?thesis
    using vs_def(2)
    by auto
qed

interpretation default_vydra: VYDRA_MDL σ 0 "λi. Some (Suc i, (τ σ i, Γ σ i))"
  using reach_elem[where ?P="λ_. True"]
  by unfold_locales auto

end

lemma reaches_inj: "reaches r s i t ==> reaches r s i t' ==> t = t'"
  using reaches_on_inj reaches_on
  by metis

lemma progress_sound:
  assumes
    "n. n < length ts ==> ts ! n = τ σ n"
    "n. n < length ts ==> τ σ n = τ σ' n"
    "n. n < length ts ==> Γ σ n = Γ σ' n"
    "n < progress phi ts"
    "bounded_future_fmla phi"
    "wf_fmla phi"
  shows "MDL.sat σ phi n MDL.sat σ' phi n"
proof -
  define run_hd where "run_hd = (λi. if i < length ts then Some (Suc i, (τ σ i, Γ σ i)) else None)"
  interpret vydra: VYDRA_MDL σ 0 run_hd
    using MDL.reach_elem[where ?P="λi. i < length ts"]
    by unfold_locales (auto simp: run_hd_def split: if_splits)
  define run_hd' where "run_hd' = (λi. if i < length ts then Some (Suc i, (τ σ' i, Γ σ' i)) else None)"
  interpret vydra': VYDRA_MDL σ' 0 run_hd'
    using MDL.reach_elem[where ?P="λi. i < length ts"]
    by unfold_locales (auto simp: run_hd'_def split: if_splits)
  have run_hd_hd': "run_hd = run_hd'"
    using assms(1-3)
    by (auto simp: run_hd_def run_hd'_def)
  have reaches_run_hd: "n length ts ==> reaches_on run_hd 0 (map (λi. (τ σ i, Γ σ i)) [0..<n]) n" for n
    by (induction n) (auto simp: run_hd_def intro: reaches_on.intros(1) intro!: reaches_on_app)
  have ts_map: "ts = map fst (map (λi. (τ σ i, Γ σ i)) [0..<length ts])"
    by (subst map_nth[symmetric]) (auto simp: assms(1))
  obtain v v' where vv_def: "reaches (run_vydra run_hd) (init_vydra 0 run_hd phi) n v" "run_vydra run_hd v = Some (v', τ σ n, vydra.sat phi n)"
    using vydra.vydra_complete[OF reaches_run_hd[OF order.refl] _ assms(5,6)] assms(4)
    unfolding ts_map[symmetric]
    by blast
  have reaches_run_hd': "n length ts ==> reaches_on run_hd' 0 (map (λi. (τ σ' i, Γ σ' i)) [0..<n]) n" for n
    by (induction n) (auto simp: run_hd'_def intro: reaches_on.intros(1) intro!: reaches_on_app)
  have ts'_map: "ts = map fst (map (λi. (τ σ' i, Γ σ' i)) [0..<length ts])"
    by (subst map_nth[symmetric]) (auto simp: assms(1,2))
  obtain w w' where ww_def: "reaches (run_vydra run_hd') (init_vydra 0 run_hd' phi) n w" "run_vydra run_hd' w = Some (w', τ σ' n, vydra'.sat phi n)"
    using vydra'.vydra_complete[OF reaches_run_hd'[OF order.refl] _ assms(5,6)] assms(4)
    unfolding ts'_map[symmetric]
    by blast
  note v_w = reaches_inj[OF vv_def(1) ww_def(1)[folded run_hd_hd']]
  show ?thesis
    using vv_def(2) ww_def(2)
    by (auto simp: run_hd_hd' v_w)
qed

end

Messung V0.5 in Prozent
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.50 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.