Theory AlphabetEnlargement_ValidationBound

theory AlphabetEnlargement_ValidationBound
  imports AlphabetEnlargement_ValidationStep
begin

subsection ‹Validation sweeps, post-state, and step bound›

subsubsection ‹Validation sweeps and tape correspondence›

text ‹Forward-sweep iteration helper.  Starting from
  ‹ae_init_config M w›, after ‹Suc k› validation steps along a
  ‹k›-pure prefix of ‹w›, the head on tape 0 is at position
  ‹Suc k› and the phase is still ‹VFwd›.  The chain is built
  by induction on ‹k›, applying ‹ae_step_val_fwd_advance› once
  per step (the LE block at position 0 takes the first step, then
  each pure block along positions ‹1…k› takes one more).›

lemma ae_validation_fwd_sweep_pure:
  fixes M :: "('q, 'a) mttm"
    and w :: "(('c :: enum) ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and s_in_Q: "s_tm M ∈ Q_tm M"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
      and k_bound: "k ≤ length w"
      and pure: "∀i < k. is_pure_block (bl_tm M) (w ! i)"
  shows "(ae_init_config M w,
            ConfigM (s_tm M, init_stage (le_tm M))
                     (mt_tape (ae_init_config M w))
                     (λi :: nat. if i = 0 then Suc k else 0))
           ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc k"
  using k_bound pure
proof (induction k)
  case 0
  let ?ts = "mt_tape (ae_init_config M w)"
  let ?n0 = "λ_ :: nat. 0 :: nat"
  let ?n1 = "λi :: nat. if i = 0 then Suc 0 else 0"
  have init_eq: "ae_init_config M w
                  = ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n0"
    by (simp add: ae_init_config_def)
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have read: "?ts 0 (?n0 0) = LE_block (le_tm M)
              ∨ is_pure_block (bl_tm M) (?ts 0 (?n0 0))"
    using ae_init_config_tape_le[OF kpos] by auto
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have gamma: "∀kk :: nat. ?ts kk (?n0 kk) ∈ gamma_block (Γ_tm M)"
    using ae_init_config_in_gamma_block[OF vM w_sub] by simp
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have step1: "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, VFwd) ?ts ?n0,
                ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, VFwd) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n0 kk)))
                ∈ mttm_step (alphabet_enlarge_delta M)"
    by (rule ae_step_val_fwd_advance[where ts = ?ts and n = ?n0,
                                     OF s_in_Q s_neq_t s_neq_r read bt_all
                                        init_stage_tail gamma buf_gamma_init])
  have post_eq:
    "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n0 kk)) = ?n1"
    by (rule ext) simp
  have step1_n1: "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                              init_dest, VFwd) ?ts ?n0,
                   ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                              init_dest, VFwd) ?ts ?n1)
                  ∈ mttm_step (alphabet_enlarge_delta M)"
    using step1 post_eq by simp
  have stage_eq: "init_stage (le_tm M)
                  = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
    unfolding init_stage_def ..
  have step1_init: "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n0,
                     ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n1)
                    ∈ mttm_step (alphabet_enlarge_delta M)"
    using step1_n1 unfolding stage_eq by simp
  have chain1: "(ae_init_config M w,
                  ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n1)
                 ∈ mttm_step (alphabet_enlarge_delta M)"
    using step1_init init_eq by simp
  show ?case using chain1 by (simp add: relpow_1)
next
  case (Suc k)
  let ?ts = "mt_tape (ae_init_config M w)"
  let ?n_k = "λi :: nat. if i = 0 then Suc k else 0"
  let ?n_Sk = "λi :: nat. if i = 0 then Suc (Suc k) else 0"
  have k_le: "k ≤ length w" using Suc.prems(1) by simp
  have pure_k: "∀i < k. is_pure_block (bl_tm M) (w ! i)"
    using Suc.prems(2) by simp
  from Suc.IH[OF k_le pure_k]
  have IH: "(ae_init_config M w,
              ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_k)
              ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc k" .
  have read_pure: "is_pure_block (bl_tm M) (w ! k)"
    using Suc.prems(2) by auto
  have Sk_pos: "1 ≤ Suc k" by simp
  have Sk_le: "Suc k ≤ length w" using Suc.prems(1) .
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have read_eq: "?ts 0 (Suc k) = w ! k"
    using ae_init_config_tape_input[OF Sk_pos Sk_le kpos] by simp
  have read: "?ts 0 (?n_k 0) = LE_block (le_tm M)
              ∨ is_pure_block (bl_tm M) (?ts 0 (?n_k 0))"
    using read_pure read_eq by simp
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have gamma: "∀kk :: nat. ?ts kk (?n_k kk) ∈ gamma_block (Γ_tm M)"
    using ae_init_config_in_gamma_block[OF vM w_sub] by simp
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have step: "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, VFwd) ?ts ?n_k,
                ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, VFwd) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n_k kk)))
                ∈ mttm_step (alphabet_enlarge_delta M)"
    by (rule ae_step_val_fwd_advance[where ts = ?ts and n = ?n_k,
                                     OF s_in_Q s_neq_t s_neq_r read bt_all
                                        init_stage_tail gamma buf_gamma_init])
  have post_eq:
    "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_k kk)) = ?n_Sk"
    by (rule ext) simp
  have step_n_Sk: "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                                init_dest, VFwd) ?ts ?n_k,
                    ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                                init_dest, VFwd) ?ts ?n_Sk)
                   ∈ mttm_step (alphabet_enlarge_delta M)"
    using step post_eq by simp
  have stage_eq: "init_stage (le_tm M)
                  = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
    unfolding init_stage_def ..
  have step_init: "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_k,
                    ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Sk)
                   ∈ mttm_step (alphabet_enlarge_delta M)"
    using step_n_Sk unfolding stage_eq by simp
  show ?case by (rule relpow_Suc_I[OF IH step_init])
qed

text ‹Return-sweep iteration helper.  Symmetric counterpart to
  the forward sweep: starting at ‹VRet› with the head on tape 0
  at position ‹p›, retreat to position 0 in ‹p› applications of
  ‹ae_step_val_ret_step›, then take one more step via
  ‹ae_step_val_ret_to_sim› to reach ‹SS1›.  Total: ‹Suc p›
  steps.  The non-LE constraint on positions ‹1…p› is hoisted
  into the goal as a ‹⟶›-form so the standard induction on
  ‹p› exposes the correct restriction at the IH.›

lemma ae_validation_ret_sweep:
  fixes M :: "('q, 'a) mttm"
    and ts :: "nat ⇒ nat ⇒ ('c :: enum ⇒ 'a)"
    and q :: 'q
    and ofs :: "nat ⇒ 'c"
    and buf :: "nat ⇒ ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)"
    and dest :: "nat ⇒ ae_dest"
    and p :: nat
  assumes q_in: "q ∈ Q_tm M"
      and tape_le: "ts (0 :: nat) 0 = LE_block (le_tm M)"
      and gamma: "∀k i. ts k i ∈ gamma_block (Γ_tm M)"
      and buf_gamma: "∀k. fst (buf k) ∈ gamma_block (Γ_tm M)
                            ∧ fst (snd (buf k)) ∈ gamma_block (Γ_tm M)
                            ∧ snd (snd (buf k)) ∈ gamma_block (Γ_tm M)"
      and bt: "∀k≥k_tm M. ∀i. ts k i = bl_block (bl_tm M)"
      and stage_tail: "(∀j≥k_tm M. ofs j = init_offset j)
                        ∧ (∀j≥k_tm M. buf j = init_buffer (le_tm M) j)
                        ∧ (∀j≥k_tm M. dest j = init_dest j)"
  shows "(∀i. 1 ≤ i ∧ i ≤ p ⟶ ts 0 i ≠ LE_block (le_tm M))
         ⟶ (ConfigM (q, ofs, buf, dest, VRet) ts
                       (λi :: nat. if i = 0 then p else 0),
              ConfigM (q, ofs, buf, dest, SS1) ts (λ_. 0))
              ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc p"
proof (induction p)
  case 0
  let ?n0 = "λ_ :: nat. 0 :: nat"
  have read: "ts (0 :: nat) (?n0 0) = LE_block (le_tm M)"
    using tape_le by simp
  have gamma_at: "∀k :: nat. ts k (?n0 k) ∈ gamma_block (Γ_tm M)"
    using gamma by simp
  have step1: "(ConfigM (q, ofs, buf, dest, VRet) ts ?n0,
                 ConfigM (q, ofs, buf, dest, SS1) ts ?n0)
                ∈ mttm_step (alphabet_enlarge_delta M)"
    by (rule ae_step_val_ret_to_sim[where ts = ts and n = ?n0,
                                    OF q_in read bt stage_tail gamma_at
                                       buf_gamma])
  have shape_eq: "(λi :: nat. if i = 0 then (0 :: nat) else 0) = ?n0"
    by (rule ext) simp
  show ?case
  proof
    assume "(∀i. 1 ≤ i ∧ i ≤ 0 ⟶ ts 0 i ≠ LE_block (le_tm M))"
    have one_step: "(ConfigM (q, ofs, buf, dest, VRet) ts
                       (λi :: nat. if i = 0 then 0 else 0),
                     ConfigM (q, ofs, buf, dest, SS1) ts (λ_. 0))
                    ∈ mttm_step (alphabet_enlarge_delta M)"
      using step1 shape_eq by simp
    thus "(ConfigM (q, ofs, buf, dest, VRet) ts
              (λi :: nat. if i = 0 then 0 else 0),
            ConfigM (q, ofs, buf, dest, SS1) ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc 0"
      by (simp add: relpow_1)
  qed
next
  case (Suc p)
  let ?n_Sp = "λi :: nat. if i = 0 then Suc p else 0"
  let ?n_p = "λi :: nat. if i = 0 then p else 0"
  show ?case
  proof
    assume tape_non_le_Sp:
      "(∀i. 1 ≤ i ∧ i ≤ Suc p ⟶ ts 0 i ≠ LE_block (le_tm M))"
    have read_non_le: "ts (0 :: nat) (?n_Sp 0) ≠ LE_block (le_tm M)"
      using tape_non_le_Sp[rule_format, of "Suc p"] by simp
    have gamma_Sp: "∀k :: nat. ts k (?n_Sp k) ∈ gamma_block (Γ_tm M)"
      using gamma by simp
    have step1: "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_Sp,
                   ConfigM (q, ofs, buf, dest, VRet) ts
                     (λkk. go_dir (if kk = (0 :: nat) then dir.L else dir.N)
                                   (?n_Sp kk)))
                  ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_ret_step[where ts = ts and n = ?n_Sp,
                                    OF q_in read_non_le bt stage_tail
                                       gamma_Sp buf_gamma])
    have post_eq:
      "(λkk :: nat. go_dir (if kk = 0 then dir.L else dir.N) (?n_Sp kk))
       = ?n_p"
      by (rule ext) simp
    have step1_p: "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_Sp,
                    ConfigM (q, ofs, buf, dest, VRet) ts ?n_p)
                   ∈ mttm_step (alphabet_enlarge_delta M)"
      using step1 post_eq by simp
    have tape_non_le_p:
      "∀i. 1 ≤ i ∧ i ≤ p ⟶ ts 0 i ≠ LE_block (le_tm M)"
      using tape_non_le_Sp by auto
    have IH_chain: "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_p,
                     ConfigM (q, ofs, buf, dest, SS1) ts (λ_. 0))
                    ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc p"
      using Suc.IH tape_non_le_p by blast
    show "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_Sp,
            ConfigM (q, ofs, buf, dest, SS1) ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc p)"
      by (rule relpow_Suc_I2[OF step1_p IH_chain])
  qed
qed

text ‹Partial return sweep: ‹m› leftward ‹VRet› steps from head
  ‹p› reach head ‹p - m›, staying in ‹VRet›, provided every visited
  cell ‹1 … p› is non-‹LE› (so the return never short-circuits to
  ‹SS1›).  This exposes each intermediate validation config as a
  reachable witness, which the full ‹ae_validation_ret_sweep› hides
  behind its composed endpoint.  Used by ‹ae_validation_prefix_markers›
  to supply return-phase witnesses for the prefix-uniqueness induction.›

lemma ae_validation_ret_partial:
  fixes M :: "('q, 'a) mttm"
    and ts :: "nat ⇒ nat ⇒ ('c :: enum ⇒ 'a)"
    and q :: 'q
    and ofs :: "nat ⇒ 'c"
    and buf :: "nat ⇒ ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)"
    and dest :: "nat ⇒ ae_dest"
    and p :: nat
  assumes q_in: "q ∈ Q_tm M"
      and gamma: "∀k i. ts k i ∈ gamma_block (Γ_tm M)"
      and buf_gamma: "∀k. fst (buf k) ∈ gamma_block (Γ_tm M)
                            ∧ fst (snd (buf k)) ∈ gamma_block (Γ_tm M)
                            ∧ snd (snd (buf k)) ∈ gamma_block (Γ_tm M)"
      and bt: "∀k≥k_tm M. ∀i. ts k i = bl_block (bl_tm M)"
      and stage_tail: "(∀j≥k_tm M. ofs j = init_offset j)
                        ∧ (∀j≥k_tm M. buf j = init_buffer (le_tm M) j)
                        ∧ (∀j≥k_tm M. dest j = init_dest j)"
      and non_le: "∀i. 1 ≤ i ∧ i ≤ p ⟶ ts 0 i ≠ LE_block (le_tm M)"
  shows "m ≤ p
         ⟶ (ConfigM (q, ofs, buf, dest, VRet) ts
                       (λi :: nat. if i = 0 then p else 0),
              ConfigM (q, ofs, buf, dest, VRet) ts
                       (λi :: nat. if i = 0 then p - m else 0))
              ∈ mttm_step (alphabet_enlarge_delta M) ^^ m"
proof (induction m)
  case 0
  have eq: "p - 0 = p" by simp
  show ?case unfolding eq by simp
next
  case (Suc m)
  let ?n_pm = "λi :: nat. if i = 0 then p - m else 0"
  let ?n_pSm = "λi :: nat. if i = 0 then p - Suc m else 0"
  show ?case
  proof
    assume Sm_le: "Suc m ≤ p"
    have m_le: "m ≤ p" using Sm_le by simp
    have pm_pos: "1 ≤ p - m" using Sm_le by simp
    have pm_le: "p - m ≤ p" by simp
    have read_non_le: "ts (0 :: nat) (?n_pm 0) ≠ LE_block (le_tm M)"
      using non_le[rule_format, of "p - m"] pm_pos pm_le by simp
    have gamma_pm: "∀k :: nat. ts k (?n_pm k) ∈ gamma_block (Γ_tm M)"
      using gamma by simp
    have step1: "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_pm,
                   ConfigM (q, ofs, buf, dest, VRet) ts
                     (λkk. go_dir (if kk = (0 :: nat) then dir.L else dir.N)
                                   (?n_pm kk)))
                  ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_ret_step[where ts = ts and n = ?n_pm,
                                    OF q_in read_non_le bt stage_tail
                                       gamma_pm buf_gamma])
    have post_eq:
      "(λkk :: nat. go_dir (if kk = 0 then dir.L else dir.N) (?n_pm kk))
       = ?n_pSm"
      using pm_pos by (rule_tac ext) simp
    have step1_pSm:
      "(ConfigM (q, ofs, buf, dest, VRet) ts ?n_pm,
         ConfigM (q, ofs, buf, dest, VRet) ts ?n_pSm)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      using step1 post_eq by simp
    have IH_chain:
      "(ConfigM (q, ofs, buf, dest, VRet) ts
                 (λi :: nat. if i = 0 then p else 0),
        ConfigM (q, ofs, buf, dest, VRet) ts ?n_pm)
        ∈ mttm_step (alphabet_enlarge_delta M) ^^ m"
      using Suc.IH m_le by blast
    show "(ConfigM (q, ofs, buf, dest, VRet) ts
                    (λi :: nat. if i = 0 then p else 0),
           ConfigM (q, ofs, buf, dest, VRet) ts ?n_pSm)
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc m"
      by (rule relpow_Suc_I[OF IH_chain step1_pSm])
  qed
qed

text ‹Tape correspondence at the initial configuration: the
  substrate's ‹init_config› tape (raw input ‹u›) corresponds to
  the AE-side ‹ae_init_config› tape (encoded block list
  ‹encode_input bl_M u›) under ‹ae_tape_correspondence›.  The
  three position regions match one-to-one:
  ▪ position ‹0›: substrate has ‹LE = le_M›; ae has ‹LE_block›
    (the correspondence's ‹tM 0 = le› conjunct);
  ▪ tape ‹0›, position ‹p = (s-1)⋅c + c_idx i + 1 ≤ length u›:
    substrate has ‹u ! (p-1)›; ae has ‹encode_input ! (s-1)› at
    offset ‹i›, which by ‹encode_input_nth› is ‹u ! (p-1)›;
  ▪ any position past the input or any tape ‹k ≠ 0›: both sides
    deliver ‹bl_M = blank_M›.›
lemma ae_tape_correspondence_init:
  fixes M :: "('q, 'a) mttm"
    and u :: "'a list"
  assumes vM: "valid_mttm M"
      and u_sub: "set u ⊆ Sigma_tm M"
  shows "∀k<k_tm M. ae_tape_correspondence (le_tm M)
              (mt_tape (init_config_mttm M u) k)
              (mt_tape (ae_init_config M
                         (encode_input (bl_tm M) u
                              :: ('c :: enum ⇒ 'a) list)) k)"
proof (intro allI impI)
  fix k :: nat
  assume k_lt: "k < k_tm M"
  have kpos: "0 < k_tm M" using k_lt by linarith
  obtain Q Σ Γ bl le δ sM tM r kM where MTTM:
    "M = MTTM Q Σ Γ bl le δ sM tM r kM"
    using mttm.exhaust by metis
  let ?w = "encode_input (bl_tm M) u :: ('c :: enum ⇒ 'a) list"
  let ?c = "card (UNIV :: 'c set)"
  show "ae_tape_correspondence (le_tm M)
          (mt_tape (init_config_mttm M u) k)
          (mt_tape (ae_init_config M ?w) k)"
    unfolding ae_tape_correspondence_def
  proof (intro conjI allI impI)
    show "mt_tape (init_config_mttm M u) k 0 = le_tm M"
      using MTTM k_lt by simp
  next
    fix s :: nat and i :: 'c
    assume s_ge: "1 ≤ s"
    let ?p = "(s - 1) * ?c + c_idx i + 1"
    have p_pos: "?p ≥ 1" by simp
    show "mt_tape (init_config_mttm M u) k ?p
          = mt_tape (ae_init_config M ?w) k s i"
    proof (cases "k = 0")
      case False
      have subst:
        "mt_tape (init_config_mttm M u) k ?p = bl_tm M"
        using MTTM False p_pos by simp
      have ae:
        "mt_tape (ae_init_config M ?w) k s i = bl_tm M"
        unfolding ae_init_config_def using s_ge False
        by (simp add: bl_block_def)
      show ?thesis using subst ae by simp
    next
      case True
      have k_eq: "k = 0" using True .
      show ?thesis
      proof (cases "?p ≤ length u")
        case False
        have p_gt: "length u < ?p" using False by simp
        have subst_bl:
          "mt_tape (init_config_mttm M u) k ?p = bl_tm M"
          using MTTM k_eq p_pos p_gt by simp
        have ae_bl:
          "mt_tape (ae_init_config M ?w) k s i = bl_tm M"
        proof (cases "s ≤ length ?w")
          case False
          thus ?thesis
            unfolding ae_init_config_def using s_ge k_eq
            by (simp add: bl_block_def)
        next
          case True
          have s_minus_1_lt: "s - 1 < length ?w"
            using True s_ge by simp
          have nth_eq:
            "(?w ! (s - 1)) i =
                (let j = (s - 1) * ?c + c_idx i in
                    if j < length u then u ! j else bl_tm M)"
            by (rule encode_input_nth[OF s_minus_1_lt])
          have j_ge: "(s - 1) * ?c + c_idx i ≥ length u"
            using p_gt by simp
          have ae_val: "(?w ! (s - 1)) i = bl_tm M"
            using nth_eq j_ge by (simp add: Let_def)
          have ae_lhs:
            "mt_tape (ae_init_config M ?w) k s i = (?w ! (s - 1)) i"
            unfolding ae_init_config_def using s_ge k_eq True kpos by simp
          show ?thesis using ae_lhs ae_val by simp
        qed
        show ?thesis using subst_bl ae_bl by simp
      next
        case True
        have p_le: "?p ≤ length u" using True .
        have subst_val:
          "mt_tape (init_config_mttm M u) k ?p
             = u ! ((s - 1) * ?c + c_idx i)"
          using MTTM k_eq p_pos p_le kpos by simp
        have c_pos: "?c > 0" using c_idx_lt_card[where x = i] by linarith
        have len_w: "length ?w = (length u + ?c - 1) div ?c"
          by (rule length_encode_input)
        have prod_lt: "(s - 1) * ?c < length u"
          using p_le by linarith
        have s_le_len_w: "s ≤ length ?w"
        proof -
          have s_times_c_eq: "s * ?c = (s - 1) * ?c + ?c"
            using s_ge by (auto simp: algebra_simps)
          have step: "s * ?c ≤ length u + ?c - 1"
            using prod_lt c_pos s_times_c_eq by linarith
          have s_div: "s * ?c div ?c = s" using c_pos by simp
          have "s = s * ?c div ?c" using s_div by simp
          also have "… ≤ (length u + ?c - 1) div ?c"
            using step by (rule div_le_mono)
          finally show ?thesis using len_w by simp
        qed
        have s_minus_1_lt: "s - 1 < length ?w"
          using s_le_len_w s_ge by simp
        have nth_eq:
          "(?w ! (s - 1)) i =
              (let j = (s - 1) * ?c + c_idx i in
                  if j < length u then u ! j else bl_tm M)"
          by (rule encode_input_nth[OF s_minus_1_lt])
        have j_lt: "(s - 1) * ?c + c_idx i < length u"
          using p_le by simp
        have ae_val: "(?w ! (s - 1)) i = u ! ((s - 1) * ?c + c_idx i)"
          using nth_eq j_lt by (simp add: Let_def)
        have ae_lhs:
          "mt_tape (ae_init_config M ?w) k s i = (?w ! (s - 1)) i"
          unfolding ae_init_config_def using s_ge k_eq s_le_len_w kpos
          by simp
        show ?thesis using subst_val ae_lhs ae_val by simp
      qed
    qed
  qed
qed

subsubsection ‹Validation post-state and step count›

text ‹Well-formed inputs (without ‹bl_block›) drive the validation
  chain to the explicit SS1 boundary configuration.  Extracted from
  the well-formed branch of ‹ae_validation_steps_bound› so that
  ‹ae_validation_post_state_canonical› can use the same chain to
  prove the simulation against the substrate's ‹init_config›
  (the steps-bound lemma's ‹obtains› form discards the explicit
  final config).

  This is the narrower companion of the general step-count form
  ‹ae_validation_phase_step_count› in theory
  ‹AlphabetEnlargement›: it gives the exact length
  ‹2 ⋅ |w| + 4› with SS1 as the only outcome under the
  stronger precondition ‹ae_input_well_formed (bl_tm M) w›,
  whereas the general form gives an existential bound
  ‹n ≤ 2 ⋅ |w| + fv› with SS1-or-reject outcomes
  for any input (well-formed or not).  The linear-speedup proof
  uses this canonical form, applied via
  ‹encode_input_well_formed› to explicit encoder-image
  inputs.›
lemma ae_validation_well_formed_to_SS1:
  fixes M :: "('q, 'a) mttm"
    and w :: "('c :: enum ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and wf: "ae_input_well_formed (bl_tm M) w"
      and s_in_Q: "s_tm M ∈ Q_tm M"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
      and le_neq_bl: "le_tm M ≠ bl_tm M"
  shows "(ae_init_config M w,
          ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                     init_dest, SS1)
                   (mt_tape (ae_init_config M w)) (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ (2 * length w + 4)"
proof -
  let ?init = "ae_init_config M w"
  let ?ts = "mt_tape ?init"
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have LE_neq_bl_block: "LE_block (le_tm M) ≠ bl_block (bl_tm M)"
    using le_neq_bl unfolding LE_block_def bl_block_def
    by (metis fun_eq_iff)
  have LE_notin: "LE_block (le_tm M) ∉ set w"
  proof -
    have le_notin: "le_tm M ∉ Sigma_tm M ∪ {bl_tm M}"
      using valid_mttm_LE_not_Sigma[OF vM] le_neq_bl by auto
    have "LE_block (le_tm M) ∉ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      using le_notin
      unfolding LE_block_def gamma_block_def by auto
    thus ?thesis using w_sub by auto
  qed
  ― ‹Determine whether all w-cells are pure or the last is padded.›
  have all_pure_or_last_padded:
    "(∀i < length w. is_pure_block (bl_tm M) (w ! i))
     ∨ (0 < length w
          ∧ (∀i < length w - 1. is_pure_block (bl_tm M) (w ! i))
          ∧ is_padded_block (bl_tm M) (w ! (length w - 1)))"
  proof (cases "length w = 0")
    case True
    thus ?thesis by simp
  next
    case False
    hence wpos: "0 < length w" by simp
    show ?thesis
    proof (cases "is_pure_block (bl_tm M) (w ! (length w - 1))")
      case True
      have "∀i < length w. is_pure_block (bl_tm M) (w ! i)"
      proof (intro allI impI)
        fix i assume i_lt: "i < length w"
        have "is_pure_block (bl_tm M) (w ! i)
              ∨ (i = length w - 1
                 ∧ is_padded_block (bl_tm M) (w ! i))"
          using wf i_lt unfolding ae_input_well_formed_def by auto
        thus "is_pure_block (bl_tm M) (w ! i)"
          using True by auto
      qed
      thus ?thesis by simp
    next
      case False
      have last_padded: "is_padded_block (bl_tm M) (w ! (length w - 1))"
      proof -
        have idx_lt: "length w - 1 < length w" using wpos by linarith
        have or_form: "is_pure_block (bl_tm M) (w ! (length w - 1))
              ∨ (length w - 1 = length w - 1
                 ∧ is_padded_block (bl_tm M) (w ! (length w - 1)))"
          using wf idx_lt unfolding ae_input_well_formed_def by blast
        thus ?thesis using False by auto
      qed
      have prefix_pure: "∀i < length w - 1. is_pure_block (bl_tm M) (w ! i)"
      proof (intro allI impI)
        fix i assume i_lt: "i < length w - 1"
        hence i_lt2: "i < length w" using wpos by linarith
        have "is_pure_block (bl_tm M) (w ! i)
              ∨ (i = length w - 1
                 ∧ is_padded_block (bl_tm M) (w ! i))"
          using wf i_lt2 unfolding ae_input_well_formed_def by auto
        thus "is_pure_block (bl_tm M) (w ! i)" using i_lt by auto
      qed
      show ?thesis using wpos prefix_pure last_padded by blast
    qed
  qed
  have tape_le: "?ts (0 :: nat) 0 = LE_block (le_tm M)"
    by (rule ae_init_config_tape_le[OF kpos])
  have gamma_all: "∀k i. ?ts k i ∈ gamma_block (Γ_tm M)"
    using ae_init_config_in_gamma_block[OF vM w_sub] by simp
  have stage_eq: "init_stage (le_tm M)
                  = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
    unfolding init_stage_def ..
  ― ‹Verify positions ‹1…Suc (length w)› on tape 0 are non-LE
      (from ‹LE_notin› for input positions; from
      ‹LE_neq_bl_block› for the blank tail).›
  have non_le: "∀i. 1 ≤ i ∧ i ≤ Suc (length w)
                     ⟶ ?ts 0 i ≠ LE_block (le_tm M)"
  proof (intro allI impI)
    fix i assume i_range: "1 ≤ i ∧ i ≤ Suc (length w)"
    have i_pos: "1 ≤ i" using i_range by simp
    consider (in_input) "i ≤ length w" | (past) "i = Suc (length w)"
      using i_range by linarith
    thus "?ts 0 i ≠ LE_block (le_tm M)"
    proof cases
      case in_input
      have eq: "?ts 0 i = w ! (i - 1)"
        using ae_init_config_tape_input[OF i_pos in_input kpos] by simp
      have "w ! (i - 1) ∈ set w" using i_pos in_input by auto
      thus ?thesis using LE_notin eq by auto
    next
      case past
      have ineq: "length w < i" using past by simp
      have eq: "?ts 0 i = bl_block (bl_tm M)"
        by (rule ae_init_config_tape_blank_after_input[OF ineq])
      have "LE_block (le_tm M) ≠ bl_block (bl_tm M)"
        by (rule LE_neq_bl_block)
      thus ?thesis using eq by force
    qed
  qed
  from all_pure_or_last_padded consider
      (all_pure) "∀i < length w. is_pure_block (bl_tm M) (w ! i)"
    | (last_padded) "0 < length w"
                     "∀i < length w - 1. is_pure_block (bl_tm M) (w ! i)"
                     "is_padded_block (bl_tm M) (w ! (length w - 1))"
    by blast
  thus ?thesis
  proof cases
    case all_pure
    let ?n_lwSS = "λi :: nat. if i = 0 then Suc (length w) else 0"
    have lw_le: "length w ≤ length w" by simp
    have sweep:
      "(?init,
          ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (length w)"
      by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                              s_neq_r lw_le all_pure])
    have lw_gt: "Suc (length w) > length w" by simp
    have read_bl: "?ts 0 (?n_lwSS 0) = bl_block (bl_tm M)"
      using ae_init_config_tape_blank_after_input[OF lw_gt] by simp
    have gamma_lwSS:
      "∀kk :: nat. ?ts kk (?n_lwSS kk) ∈ gamma_block (Γ_tm M)"
      using gamma_all by simp
    have step_to_ret:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_lwSS,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_fwd_to_ret[where ts = ?ts and n = ?n_lwSS,
            OF s_in_Q s_neq_t s_neq_r read_bl bt_all init_stage_tail
               gamma_lwSS buf_gamma_init])
    have step_to_ret_init:
      "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_lwSS,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_to_ret unfolding stage_eq by simp
    have post_sweep:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc (length w))"
      by (rule relpow_Suc_I[OF sweep step_to_ret_init])
    have ret_arrow:
      "(∀i. 1 ≤ i ∧ i ≤ Suc (length w)
            ⟶ ?ts 0 i ≠ LE_block (le_tm M))
       ⟶ (ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VRet) ?ts ?n_lwSS,
            ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc (length w))"
      by (rule ae_validation_ret_sweep[OF s_in_Q tape_le gamma_all
                                          buf_gamma_init bt_all init_stage_tail])
    have ret_chain:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ Suc (Suc (length w))"
      using ret_arrow non_le by (rule mp)
    have full_chain_pre:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ (Suc (Suc (length w)) + Suc (Suc (length w)))"
    proof -
      have comp:
        "(?init,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc (length w))
              O mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc (length w))"
        using post_sweep ret_chain by (rule relcompI)
      thus ?thesis by (simp only: relpow_add)
    qed
    have total_eq:
      "Suc (Suc (length w)) + Suc (Suc (length w)) = 2 * length w + 4"
      by simp
    have full_chain:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ (2 * length w + 4)"
      using full_chain_pre unfolding total_eq .
    show ?thesis using full_chain .
  next
    case last_padded
    let ?lw = "length w"
    let ?lwm1 = "length w - 1"
    let ?n_lw = "λi :: nat. if i = 0 then ?lw else 0"
    let ?n_lwSS = "λi :: nat. if i = 0 then Suc ?lw else 0"
    have wpos: "0 < ?lw" using last_padded(1) .
    have m1_le: "?lwm1 ≤ ?lw" by simp
    have prefix_pure: "∀i < ?lwm1. is_pure_block (bl_tm M) (w ! i)"
      using last_padded(2) .
    have sweep:
      "(?init,
          ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                   (λi :: nat. if i = 0 then Suc ?lwm1 else 0))
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc ?lwm1"
      by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                              s_neq_r m1_le prefix_pure])
    have suc_m1_eq: "Suc ?lwm1 = ?lw" using wpos by simp
    have sweep_lw:
      "(?init,
          ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_lw)
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ ?lw"
      using sweep unfolding suc_m1_eq .
    have lw_pos: "1 ≤ ?lw" using wpos by linarith
    have lw_le: "?lw ≤ ?lw" by simp
    have read_at_lw_eq: "?ts 0 ?lw = w ! ?lwm1"
      using ae_init_config_tape_input[OF lw_pos lw_le kpos] by simp
    have read_padded:
      "is_padded_block (bl_tm M) (?ts 0 (?n_lw 0))"
      using read_at_lw_eq last_padded(3) by simp
    have gamma_lw:
      "∀kk :: nat. ?ts kk (?n_lw kk) ∈ gamma_block (Γ_tm M)"
      using gamma_all by simp
    have step_to_pad:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_lw,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts
                (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                               (?n_lw kk)))
          ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_fwd_to_padded[where ts = ?ts and n = ?n_lw,
            OF s_in_Q s_neq_t s_neq_r read_padded bt_all init_stage_tail
               gamma_lw buf_gamma_init])
    have post_eq_pad:
      "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_lw kk))
       = ?n_lwSS"
      by (rule ext) simp
    have step_to_pad_norm:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_lw,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_to_pad post_eq_pad by simp
    have step_to_pad_init:
      "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_lw,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_to_pad_norm unfolding stage_eq by simp
    have lw_gt: "Suc ?lw > ?lw" by simp
    have read_bl_lwSS: "?ts 0 (?n_lwSS 0) = bl_block (bl_tm M)"
      using ae_init_config_tape_blank_after_input[OF lw_gt] by simp
    have gamma_lwSS:
      "∀kk :: nat. ?ts kk (?n_lwSS kk) ∈ gamma_block (Γ_tm M)"
      using gamma_all by simp
    have step_pad_to_ret:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_lwSS,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_pad_to_ret[where ts = ?ts and n = ?n_lwSS,
            OF s_in_Q read_bl_lwSS bt_all init_stage_tail
               gamma_lwSS buf_gamma_init])
    have chain_lw_to_VFwdPad:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc ?lw"
      by (rule relpow_Suc_I[OF sweep_lw step_to_pad_init])
    have chain_to_VRet:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS)
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc ?lw)"
      by (rule relpow_Suc_I[OF chain_lw_to_VFwdPad step_pad_to_ret])
    have ret_arrow:
      "(∀i. 1 ≤ i ∧ i ≤ Suc ?lw
            ⟶ ?ts 0 i ≠ LE_block (le_tm M))
       ⟶ (ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VRet) ?ts ?n_lwSS,
            ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc ?lw)"
      by (rule ae_validation_ret_sweep[OF s_in_Q tape_le gamma_all
                                          buf_gamma_init bt_all init_stage_tail])
    have ret_chain:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VRet) ?ts ?n_lwSS,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ Suc (Suc ?lw)"
      using ret_arrow non_le by (rule mp)
    have full_chain_pre:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ (Suc (Suc ?lw) + Suc (Suc ?lw))"
    proof -
      have comp:
        "(?init,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc ?lw)
              O mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc ?lw)"
        using chain_to_VRet ret_chain by (rule relcompI)
      thus ?thesis by (simp only: relpow_add)
    qed
    have total_eq:
      "Suc (Suc ?lw) + Suc (Suc ?lw) = 2 * ?lw + 4"
      by simp
    have full_chain:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ (2 * ?lw + 4)"
      using full_chain_pre unfolding total_eq .
    show ?thesis using full_chain .
  qed
qed

text ‹Every prefix of the validation run carries a ∗‹marker›
  witness: a config reachable in exactly ‹i› steps whose stage index
  is one of ‹VFwd› / ‹VFwdPad› / ‹VRet› (i.e.\ still inside the
  validation sweep, not yet at ‹SS1› nor rejected), for every
  ‹i < 2 * length w + 4›.  Forward witnesses for ‹i ≤ length w›
  come from ‹ae_validation_fwd_sweep_pure› at parameter ‹i - 1›;
  the boundary slot ‹i = Suc (length w)› is ‹VFwd› (all-pure) or
  ‹VFwdPad› (last-padded); return witnesses come from the partial
  return sweep.  This is the witness half of the prefix-uniqueness
  argument in ‹ae_validation_prefix_markers›.›

lemma ae_validation_prefix_witnesses:
  fixes M :: "('q, 'a) mttm"
    and w :: "('c :: enum ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and wf: "ae_input_well_formed (bl_tm M) w"
      and s_in_Q: "s_tm M ∈ Q_tm M"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
      and le_neq_bl: "le_tm M ≠ bl_tm M"
  shows "∀i<2 * length w + 4. ∃d.
            (ae_init_config M w, d)
                ∈ mttm_step (alphabet_enlarge_delta M) ^^ i
              ∧ snd (snd (snd (snd (mt_state d))))
                    ∈ {VFwd, VFwdPad, VRet}"
proof -
  let ?init = "ae_init_config M w"
  let ?ts = "mt_tape ?init"
  let ?R = "mttm_step (alphabet_enlarge_delta M)"
  let ?lw = "length w"
  let ?vfwd = "λh :: nat. ConfigM (s_tm M, init_offset,
                  init_buffer (le_tm M), init_dest, VFwd) ?ts
                  (λi :: nat. if i = 0 then h else 0)"
  let ?vret = "λh :: nat. ConfigM (s_tm M, init_offset,
                  init_buffer (le_tm M), init_dest, VRet) ?ts
                  (λi :: nat. if i = 0 then h else 0)"
  let ?vpad = "λh :: nat. ConfigM (s_tm M, init_offset,
                  init_buffer (le_tm M), init_dest, VFwdPad) ?ts
                  (λi :: nat. if i = 0 then h else 0)"
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have LE_neq_bl_block: "LE_block (le_tm M) ≠ bl_block (bl_tm M)"
    using le_neq_bl unfolding LE_block_def bl_block_def
    by (metis fun_eq_iff)
  have LE_notin: "LE_block (le_tm M) ∉ set w"
  proof -
    have le_notin: "le_tm M ∉ Sigma_tm M ∪ {bl_tm M}"
      using valid_mttm_LE_not_Sigma[OF vM] le_neq_bl by auto
    have "LE_block (le_tm M) ∉ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      using le_notin unfolding LE_block_def gamma_block_def by auto
    thus ?thesis using w_sub by auto
  qed
  have tape_le: "?ts (0 :: nat) 0 = LE_block (le_tm M)"
    by (rule ae_init_config_tape_le[OF kpos])
  have gamma_all: "∀k i. ?ts k i ∈ gamma_block (Γ_tm M)"
    using ae_init_config_in_gamma_block[OF vM w_sub] by simp
  have stage_eq: "init_stage (le_tm M)
                  = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
    unfolding init_stage_def ..
  have non_le_Slw: "∀i. 1 ≤ i ∧ i ≤ Suc ?lw
                       ⟶ ?ts 0 i ≠ LE_block (le_tm M)"
  proof (intro allI impI)
    fix i assume i_range: "1 ≤ i ∧ i ≤ Suc ?lw"
    have i_pos: "1 ≤ i" using i_range by simp
    consider (in_input) "i ≤ ?lw" | (past) "i = Suc ?lw"
      using i_range by linarith
    thus "?ts 0 i ≠ LE_block (le_tm M)"
    proof cases
      case in_input
      have eq: "?ts 0 i = w ! (i - 1)"
        using ae_init_config_tape_input[OF i_pos in_input kpos] by simp
      have "w ! (i - 1) ∈ set w" using i_pos in_input by auto
      thus ?thesis using LE_notin eq by auto
    next
      case past
      have ineq: "?lw < i" using past by simp
      have eq: "?ts 0 i = bl_block (bl_tm M)"
        by (rule ae_init_config_tape_blank_after_input[OF ineq])
      thus ?thesis using LE_neq_bl_block by force
    qed
  qed
  ― ‹Forward witnesses for ‹i ≤ length w›, uniformly (the
      pure-prefix ‹∀j < i-1› holds for any well-formed input).›
  have vfwd_wit: "⋀i. i ≤ ?lw ⟹ (?init, ?vfwd i) ∈ ?R ^^ i"
  proof -
    fix i assume i_le: "i ≤ ?lw"
    show "(?init, ?vfwd i) ∈ ?R ^^ i"
    proof (cases "i = 0")
      case True
      have head0: "(λi :: nat. if i = 0 then 0 else (0 :: nat)) = (λ_. 0)"
        by simp
      have eq0: "?vfwd 0 = ?init"
        unfolding ae_init_config_def init_stage_def head0 by simp
      have "(?init, ?vfwd 0) ∈ ?R ^^ 0" using eq0 relpow_0_I by metis
      thus ?thesis unfolding True .
    next
      case False
      hence i_pos: "1 ≤ i" by simp
      have k_le: "i - 1 ≤ ?lw" using i_le by simp
      have pure_short: "∀j < i - 1. is_pure_block (bl_tm M) (w ! j)"
      proof (intro allI impI)
        fix j assume j_lt: "j < i - 1"
        have j_lt_lw: "j < ?lw" using j_lt i_le by linarith
        have j_neq: "j ≠ ?lw - 1" using j_lt i_le by linarith
        have "is_pure_block (bl_tm M) (w ! j)
              ∨ (j = ?lw - 1 ∧ is_padded_block (bl_tm M) (w ! j))"
          using wf j_lt_lw unfolding ae_input_well_formed_def by auto
        thus "is_pure_block (bl_tm M) (w ! j)" using j_neq by auto
      qed
      have sweep:
        "(?init, ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                          (λj :: nat. if j = 0 then Suc (i - 1) else 0))
            ∈ ?R ^^ Suc (i - 1)"
        by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                                s_neq_r k_le pure_short])
      have suci: "Suc (i - 1) = i" using i_pos by simp
      show ?thesis using sweep unfolding suci stage_eq by simp
    qed
  qed
  ― ‹Classify the input: all blocks pure, or the last padded.›
  have all_pure_or_last_padded:
    "(∀i < ?lw. is_pure_block (bl_tm M) (w ! i))
     ∨ (0 < ?lw
          ∧ (∀i < ?lw - 1. is_pure_block (bl_tm M) (w ! i))
          ∧ is_padded_block (bl_tm M) (w ! (?lw - 1)))"
  proof (cases "?lw = 0")
    case True thus ?thesis by simp
  next
    case False
    hence wpos: "0 < ?lw" by simp
    show ?thesis
    proof (cases "is_pure_block (bl_tm M) (w ! (?lw - 1))")
      case True
      have "∀i < ?lw. is_pure_block (bl_tm M) (w ! i)"
      proof (intro allI impI)
        fix i assume i_lt: "i < ?lw"
        have "is_pure_block (bl_tm M) (w ! i)
              ∨ (i = ?lw - 1 ∧ is_padded_block (bl_tm M) (w ! i))"
          using wf i_lt unfolding ae_input_well_formed_def by auto
        thus "is_pure_block (bl_tm M) (w ! i)" using True by auto
      qed
      thus ?thesis by simp
    next
      case False
      have last_padded: "is_padded_block (bl_tm M) (w ! (?lw - 1))"
      proof -
        have idx_lt: "?lw - 1 < ?lw" using wpos by linarith
        have "is_pure_block (bl_tm M) (w ! (?lw - 1))
              ∨ (?lw - 1 = ?lw - 1
                 ∧ is_padded_block (bl_tm M) (w ! (?lw - 1)))"
          using wf idx_lt unfolding ae_input_well_formed_def by blast
        thus ?thesis using False by auto
      qed
      have prefix_pure: "∀i < ?lw - 1. is_pure_block (bl_tm M) (w ! i)"
      proof (intro allI impI)
        fix i assume i_lt: "i < ?lw - 1"
        hence i_lt2: "i < ?lw" using wpos by linarith
        have "is_pure_block (bl_tm M) (w ! i)
              ∨ (i = ?lw - 1 ∧ is_padded_block (bl_tm M) (w ! i))"
          using wf i_lt2 unfolding ae_input_well_formed_def by auto
        thus "is_pure_block (bl_tm M) (w ! i)" using i_lt by auto
      qed
      show ?thesis using wpos prefix_pure last_padded by blast
    qed
  qed
  ― ‹Boundary witness at step ‹Suc (length w)›: ‹VFwd› head
      ‹Suc lw› (all-pure) or ‹VFwdPad› head ‹Suc lw› (last-padded).›
  have boundary_wit: "∃d. (?init, d) ∈ ?R ^^ Suc ?lw
            ∧ snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
  proof -
    from all_pure_or_last_padded consider
        (all_pure) "∀i < ?lw. is_pure_block (bl_tm M) (w ! i)"
      | (last_padded) "0 < ?lw"
                       "∀i < ?lw - 1. is_pure_block (bl_tm M) (w ! i)"
                       "is_padded_block (bl_tm M) (w ! (?lw - 1))"
      by blast
    thus ?thesis
    proof cases
      case all_pure
      have lw_le: "?lw ≤ ?lw" by simp
      have sweep:
        "(?init, ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                          (λi :: nat. if i = 0 then Suc ?lw else 0))
            ∈ ?R ^^ Suc ?lw"
        by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                                s_neq_r lw_le all_pure])
      have reach: "(?init, ?vfwd (Suc ?lw)) ∈ ?R ^^ Suc ?lw"
        using sweep unfolding stage_eq by simp
      have "snd (snd (snd (snd (mt_state (?vfwd (Suc ?lw))))))
              ∈ {VFwd, VFwdPad, VRet}" by simp
      thus ?thesis using reach by blast
    next
      case last_padded
      let ?n_lw = "λi :: nat. if i = 0 then ?lw else 0"
      have wpos: "0 < ?lw" using last_padded(1) .
      have m1_le: "?lw - 1 ≤ ?lw" by simp
      have sweep:
        "(?init, ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                   (λi :: nat. if i = 0 then Suc (?lw - 1) else 0))
            ∈ ?R ^^ Suc (?lw - 1)"
        by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                                s_neq_r m1_le last_padded(2)])
      have suc_m1_eq: "Suc (?lw - 1) = ?lw" using wpos by simp
      have sweep_lw: "(?init, ?vfwd ?lw) ∈ ?R ^^ ?lw"
        using sweep unfolding suc_m1_eq stage_eq by simp
      have lw_pos: "1 ≤ ?lw" using wpos by linarith
      have lw_le: "?lw ≤ ?lw" by simp
      have read_at_lw_eq: "?ts 0 ?lw = w ! (?lw - 1)"
        using ae_init_config_tape_input[OF lw_pos lw_le kpos] by simp
      have read_padded: "is_padded_block (bl_tm M) (?ts 0 (?n_lw 0))"
        using read_at_lw_eq last_padded(3) by simp
      have gamma_lw: "∀kk :: nat. ?ts kk (?n_lw kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_to_pad:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_lw,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n_lw kk)))
            ∈ ?R"
        by (rule ae_step_val_fwd_to_padded[where ts = ?ts and n = ?n_lw,
              OF s_in_Q s_neq_t s_neq_r read_padded bt_all init_stage_tail
                 gamma_lw buf_gamma_init])
      have post_eq_pad:
        "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_lw kk))
         = (λi :: nat. if i = 0 then Suc ?lw else 0)"
        by (rule ext) simp
      have step_to_pad_norm: "(?vfwd ?lw, ?vpad (Suc ?lw)) ∈ ?R"
        using step_to_pad post_eq_pad by simp
      have reach: "(?init, ?vpad (Suc ?lw)) ∈ ?R ^^ Suc ?lw"
        by (rule relpow_Suc_I[OF sweep_lw step_to_pad_norm])
      have "snd (snd (snd (snd (mt_state (?vpad (Suc ?lw))))))
              ∈ {VFwd, VFwdPad, VRet}" by simp
      thus ?thesis using reach by blast
    qed
  qed
  ― ‹Pivot witness into ‹VRet› at head ‹Suc lw›, reached in
      ‹Suc (Suc lw)› steps (both classification cases).›
  have to_VRet: "(?init, ?vret (Suc ?lw)) ∈ ?R ^^ Suc (Suc ?lw)"
  proof -
    from all_pure_or_last_padded consider
        (all_pure) "∀i < ?lw. is_pure_block (bl_tm M) (w ! i)"
      | (last_padded) "0 < ?lw"
                       "∀i < ?lw - 1. is_pure_block (bl_tm M) (w ! i)"
                       "is_padded_block (bl_tm M) (w ! (?lw - 1))"
      by blast
    thus ?thesis
    proof cases
      case all_pure
      let ?n_Slw = "λi :: nat. if i = 0 then Suc ?lw else 0"
      have lw_le: "?lw ≤ ?lw" by simp
      have sweep: "(?init, ?vfwd (Suc ?lw)) ∈ ?R ^^ Suc ?lw"
        using ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                  s_neq_r lw_le all_pure] unfolding stage_eq by simp
      have lw_gt: "Suc ?lw > ?lw" by simp
      have read_bl: "?ts 0 (?n_Slw 0) = bl_block (bl_tm M)"
        using ae_init_config_tape_blank_after_input[OF lw_gt] by simp
      have gamma_Slw: "∀kk :: nat. ?ts kk (?n_Slw kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_to_ret: "(?vfwd (Suc ?lw), ?vret (Suc ?lw)) ∈ ?R"
        by (rule ae_step_val_fwd_to_ret[where ts = ?ts and n = ?n_Slw,
              OF s_in_Q s_neq_t s_neq_r read_bl bt_all init_stage_tail
                 gamma_Slw buf_gamma_init])
      show ?thesis by (rule relpow_Suc_I[OF sweep step_to_ret])
    next
      case last_padded
      let ?n_lw = "λi :: nat. if i = 0 then ?lw else 0"
      let ?n_Slw = "λi :: nat. if i = 0 then Suc ?lw else 0"
      have wpos: "0 < ?lw" using last_padded(1) .
      have m1_le: "?lw - 1 ≤ ?lw" by simp
      have sweep:
        "(?init, ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                   (λi :: nat. if i = 0 then Suc (?lw - 1) else 0))
            ∈ ?R ^^ Suc (?lw - 1)"
        by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                                s_neq_r m1_le last_padded(2)])
      have suc_m1_eq: "Suc (?lw - 1) = ?lw" using wpos by simp
      have sweep_lw: "(?init, ?vfwd ?lw) ∈ ?R ^^ ?lw"
        using sweep unfolding suc_m1_eq stage_eq by simp
      have lw_pos: "1 ≤ ?lw" using wpos by linarith
      have lw_le: "?lw ≤ ?lw" by simp
      have read_at_lw_eq: "?ts 0 ?lw = w ! (?lw - 1)"
        using ae_init_config_tape_input[OF lw_pos lw_le kpos] by simp
      have read_padded: "is_padded_block (bl_tm M) (?ts 0 (?n_lw 0))"
        using read_at_lw_eq last_padded(3) by simp
      have gamma_lw: "∀kk :: nat. ?ts kk (?n_lw kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_to_pad:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_lw,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n_lw kk)))
            ∈ ?R"
        by (rule ae_step_val_fwd_to_padded[where ts = ?ts and n = ?n_lw,
              OF s_in_Q s_neq_t s_neq_r read_padded bt_all init_stage_tail
                 gamma_lw buf_gamma_init])
      have post_eq_pad:
        "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_lw kk))
         = ?n_Slw"
        by (rule ext) simp
      have step_to_pad_norm: "(?vfwd ?lw, ?vpad (Suc ?lw)) ∈ ?R"
        using step_to_pad post_eq_pad by simp
      have chain_lw_to_VFwdPad: "(?init, ?vpad (Suc ?lw)) ∈ ?R ^^ Suc ?lw"
        by (rule relpow_Suc_I[OF sweep_lw step_to_pad_norm])
      have read_bl_Slw: "?ts 0 (?n_Slw 0) = bl_block (bl_tm M)"
        using ae_init_config_tape_blank_after_input[OF lessI] by simp
      have gamma_Slw: "∀kk :: nat. ?ts kk (?n_Slw kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_pad_to_ret: "(?vpad (Suc ?lw), ?vret (Suc ?lw)) ∈ ?R"
        by (rule ae_step_val_pad_to_ret[where ts = ?ts and n = ?n_Slw,
              OF s_in_Q read_bl_Slw bt_all init_stage_tail
                 gamma_Slw buf_gamma_init])
      show ?thesis
        by (rule relpow_Suc_I[OF chain_lw_to_VFwdPad step_pad_to_ret])
    qed
  qed
  ― ‹Return witnesses: ‹m› leftward steps from the pivot reach
      ‹VRet› head ‹Suc lw - m› in ‹Suc (Suc lw) + m› steps.›
  have ret_reach: "⋀m. m ≤ Suc ?lw
            ⟹ (?init, ?vret (Suc ?lw - m)) ∈ ?R ^^ (Suc (Suc ?lw) + m)"
  proof -
    fix m assume mle: "m ≤ Suc ?lw"
    have rp: "(?vret (Suc ?lw), ?vret (Suc ?lw - m)) ∈ ?R ^^ m"
      by (rule mp[OF ae_validation_ret_partial[OF s_in_Q gamma_all
            buf_gamma_init bt_all init_stage_tail non_le_Slw] mle])
    have "(?init, ?vret (Suc ?lw - m)) ∈ ?R ^^ Suc (Suc ?lw) O ?R ^^ m"
      using to_VRet rp by (rule relcompI)
    thus "(?init, ?vret (Suc ?lw - m)) ∈ ?R ^^ (Suc (Suc ?lw) + m)"
      by (simp only: relpow_add)
  qed
  ― ‹Assemble: each step ‹i < 2 lw + 4› falls in the forward,
      boundary, or return region.›
  show ?thesis
  proof (intro allI impI)
    fix i :: nat assume i_lt: "i < 2 * ?lw + 4"
    consider (fwd) "i ≤ ?lw" | (bd) "i = Suc ?lw" | (ret) "Suc ?lw < i"
      by linarith
    thus "∃d. (?init, d) ∈ ?R ^^ i
              ∧ snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
    proof cases
      case fwd
      have "(?init, ?vfwd i) ∈ ?R ^^ i" by (rule vfwd_wit[OF fwd])
      moreover have "snd (snd (snd (snd (mt_state (?vfwd i)))))
                       ∈ {VFwd, VFwdPad, VRet}" by simp
      ultimately show ?thesis by blast
    next
      case bd
      show ?thesis using boundary_wit unfolding bd by blast
    next
      case ret
      define m where "m = i - Suc (Suc ?lw)"
      have i_ge: "Suc (Suc ?lw) ≤ i" using ret by simp
      have m_le: "m ≤ Suc ?lw" using i_lt m_def by simp
      have i_eq: "Suc (Suc ?lw) + m = i" using i_ge m_def by simp
      have "(?init, ?vret (Suc ?lw - m)) ∈ ?R ^^ i"
        using ret_reach[OF m_le] unfolding i_eq .
      moreover have "snd (snd (snd (snd (mt_state (?vret (Suc ?lw - m))))))
                       ∈ {VFwd, VFwdPad, VRet}" by simp
      ultimately show ?thesis by blast
    qed
  qed
qed

text ‹Prefix uniqueness: every config reachable from ‹ae_init_config›
  in ‹i < 2 * length w + 4› steps is a validation marker (stage index
  ‹VFwd› / ‹VFwdPad› / ‹VRet›).  This is the invariant the relpow
  validation-functional needs, and is ∗‹det-free›: the validation
  sweep is functional regardless of ‹M›'s (non)determinism, since the
  only nondeterministic substep of ‹alphabet_enlarge_delta› (the
  ‹SS4›-to-‹SS5› transition) is never reached before ‹SS1›.  Proof:
  strong induction on ‹i›;
  the induction hypothesis supplies the relpow-functional's invariant
  premise, so the arbitrary reachable ‹d› is forced equal to the
  marker witness exhibited by ‹ae_validation_prefix_witnesses›.›

lemma ae_validation_prefix_markers:
  fixes M :: "('q, 'a) mttm"
    and w :: "('c :: enum ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and wf: "ae_input_well_formed (bl_tm M) w"
      and s_in_Q: "s_tm M ∈ Q_tm M"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
      and le_neq_bl: "le_tm M ≠ bl_tm M"
  shows "∀i<2 * length w + 4. ∀d.
            (ae_init_config M w, d)
                ∈ mttm_step (alphabet_enlarge_delta M) ^^ i
              ⟶ snd (snd (snd (snd (mt_state d))))
                    ∈ {VFwd, VFwdPad, VRet}"
proof -
  let ?init = "ae_init_config M w"
  let ?R = "mttm_step (alphabet_enlarge_delta M)"
  let ?n_val = "2 * length w + 4"
  have wit: "∀i<?n_val. ∃d. (?init, d) ∈ ?R ^^ i
              ∧ snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
    by (rule ae_validation_prefix_witnesses[OF vM w_sub wf s_in_Q
                                              s_neq_t s_neq_r le_neq_bl])
  have main: "∀i0. i0 < ?n_val
                ⟶ (∀d. (?init, d) ∈ ?R ^^ i0
                          ⟶ snd (snd (snd (snd (mt_state d))))
                                ∈ {VFwd, VFwdPad, VRet})"
  proof (rule allI)
    fix i1 :: nat
    show "i1 < ?n_val
            ⟶ (∀d. (?init, d) ∈ ?R ^^ i1
                  ⟶ snd (snd (snd (snd (mt_state d))))
                        ∈ {VFwd, VFwdPad, VRet})"
    proof (induction i1 rule: less_induct)
      case (less i)
      show ?case
      proof (rule impI)
        assume i_lt: "i < ?n_val"
        show "∀d. (?init, d) ∈ ?R ^^ i
                    ⟶ snd (snd (snd (snd (mt_state d))))
                          ∈ {VFwd, VFwdPad, VRet}"
        proof (intro allI impI)
          fix d assume reach: "(?init, d) ∈ ?R ^^ i"
          have inv: "∀j<i. ∀d'. (?init, d') ∈ ?R ^^ j
                      ⟶ snd (snd (snd (snd (mt_state d'))))
                            ∈ {VFwd, VFwdPad, VRet}"
          proof (intro allI impI)
            fix j d' assume j_lt: "j < i" and reach': "(?init, d') ∈ ?R ^^ j"
            have "j < ?n_val" using j_lt i_lt by simp
            thus "snd (snd (snd (snd (mt_state d')))) ∈ {VFwd, VFwdPad, VRet}"
              using less.IH[OF j_lt] reach' by blast
          qed
          obtain wd where wreach: "(?init, wd) ∈ ?R ^^ i"
            and wmark: "snd (snd (snd (snd (mt_state wd)))) ∈ {VFwd, VFwdPad, VRet}"
            using wit i_lt by blast
          have "d = wd"
            by (rule mttm_step_alphabet_enlarge_val_relpow_functional
                       [OF le_neq_bl reach wreach inv])
          thus "snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
            using wmark by simp
        qed
      qed
    qed
  qed
  show ?thesis using main by blast
qed

lemma ae_validation_post_state_canonical:
  fixes M :: "('q, 'a) mttm"
    and u :: "'a list"
  assumes vM: "valid_mttm M"
      and u_sub: "set u ⊆ Sigma_tm M"
      and le_neq_bl: "le_tm M ≠ bl_tm M"
  obtains n :: nat and c' where
      "(ae_init_config M (encode_input (bl_tm M) u), c')
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ n"
    and "ae_simulates M
            (init_config_mttm M u)
            (c' :: ('c :: enum ⇒ 'a,
                    'q × ('a, 'c) ae_stage) mt_config)"
    and "ae_buffer_in_gamma_block M c'"
    and "∀kk<k_tm M. mt_tape c' kk 0 = LE_block (le_tm M)"
    and "∀i<n. ∀d :: ('c :: enum ⇒ 'a,
                          'q × ('a, 'c) ae_stage) mt_config.
            (ae_init_config M (encode_input (bl_tm M) u), d)
                ∈ mttm_step (alphabet_enlarge_delta M) ^^ i
              ⟶ snd (snd (snd (snd (mt_state d))))
                    ∈ {VFwd, VFwdPad, VRet}"
proof -
  let ?w = "encode_input (bl_tm M) u :: ('c :: enum ⇒ 'a) list"
  let ?init = "ae_init_config M ?w"
  let ?subst_init = "init_config_mttm M u :: ('a, 'q) mt_config"
  have w_sub: "set ?w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
    by (rule encode_input_in_gamma_block[OF u_sub])
  have wf: "ae_input_well_formed (bl_tm M) ?w"
    by (rule encode_input_well_formed[OF vM u_sub])
  have s_in_Q: "s_tm M ∈ Q_tm M" by (rule s_tm_in_Q_tm[OF vM])
  ― ‹Tape correspondence is shared across the s-degenerate and
      s-nondegenerate cases (the chain doesn't modify the tape).›
  have tape_corr:
    "∀k<k_tm M. ae_tape_correspondence (le_tm M)
            (mt_tape ?subst_init k) (mt_tape ?init k)"
    by (rule ae_tape_correspondence_init[OF vM u_sub])
  ― ‹Gamma-block invariant on the M'-tape: also shared across
      both cases since the validation chain in the nondegen case
      reuses ‹mt_tape ?init› verbatim (no writes).›
  have gamma_block_init: "ae_tape_in_gamma_block M ?init"
    unfolding ae_tape_in_gamma_block_def
  proof (intro conjI)
    show "∀k p. mt_tape ?init k p ∈ gamma_block (Γ_tm M)"
      using ae_init_config_in_gamma_block[OF vM w_sub] by simp
  next
    show "∀j≥k_tm M. ∀p. mt_tape ?init j p = bl_block (bl_tm M)"
      using ae_init_config_tape_blank_tail by blast
  qed
  ― ‹Position correspondence: substrate's ‹n_M k = 0›; ae's
      ‹n_M' k = 0›; ‹ae_decode_pos 0 _ = 0›.›
  have ae_pos_zero: "∀k. mt_pos ?init k = 0"
    unfolding ae_init_config_def by simp
  have subst_pos_zero: "∀k. mt_pos ?subst_init k = 0"
    by (cases M) simp
  have pos_corr_init:
    "∀k. mt_pos ?subst_init k
            = ae_decode_pos (mt_pos ?init k) ((init_offset :: nat ⇒ 'c) k)"
    using ae_pos_zero subst_pos_zero
    unfolding ae_decode_pos_def by simp
  consider (degen) "s_tm M = t_tm M ∨ s_tm M = r_tm M"
         | (nondegen) "s_tm M ≠ t_tm M ∧ s_tm M ≠ r_tm M"
    by blast
  thus ?thesis
  proof cases
    case degen
    ― ‹‹n = 0›: chain is reflexive; simulation's halt-branch fires.›
    have chain_0:
      "(?init, ?init) ∈ mttm_step (alphabet_enlarge_delta M) ^^ 0"
      by simp
    have qM_subst: "mt_state ?subst_init = s_tm M"
      by (cases M) simp
    have init_state:
      "mt_state ?init = (s_tm M, init_offset,
                          init_buffer (le_tm M), init_dest, VFwd)"
      unfolding ae_init_config_def init_stage_def by simp
    have simulation: "ae_simulates M ?subst_init ?init"
      unfolding ae_simulates_def Let_def init_state init_stage_def
      using qM_subst tape_corr pos_corr_init degen gamma_block_init by simp
    ― ‹‹buf_gamma›: ‹?init›'s state buffer is ‹init_buffer (le_tm M)›,
        which is constant ‹LE_block (le_tm M)› in every slot;
        ‹init_buffer_in_gamma_block_at_M› discharges.›
    have buf_gamma_init: "ae_buffer_in_gamma_block M ?init"
      unfolding ae_buffer_in_gamma_block_def init_state init_stage_def
      using init_buffer_in_gamma_block_at_M[OF vM] by simp
    ― ‹‹le_anchor›: position 0 of every M'-tape is ‹LE_block (le_tm M)›
        by ‹ae_init_config_def›.›
    have le_anchor_init:
        "∀kk<k_tm M. mt_tape ?init kk 0 = LE_block (le_tm M)"
      by (auto intro: ae_init_config_tape_le)
    ― ‹‹n = 0›, so the prefix-marker clause is vacuous.›
    have markers_0:
      "∀i<(0 :: nat). ∀d.
          (?init, d) ∈ mttm_step (alphabet_enlarge_delta M) ^^ i
            ⟶ snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
      by simp
    show ?thesis
      using chain_0 simulation buf_gamma_init le_anchor_init markers_0
      by (rule that)
  next
    case nondegen
    ― ‹Build SS1-landing chain via helper; simulation's SS1-branch
        fires.›
    have s_neq_t: "s_tm M ≠ t_tm M" using nondegen by simp
    have s_neq_r: "s_tm M ≠ r_tm M" using nondegen by simp
    let ?c' = "ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                          init_dest, SS1)
                       (mt_tape ?init) (λ_ :: nat. (0 :: nat))
                  :: ('c ⇒ 'a, 'q × ('a, 'c) ae_stage) mt_config"
    have chain:
      "(?init, ?c') ∈ mttm_step (alphabet_enlarge_delta M)
                        ^^ (2 * length ?w + 4)"
      by (rule ae_validation_well_formed_to_SS1[OF vM w_sub wf
            s_in_Q s_neq_t s_neq_r le_neq_bl])
    have qM_subst: "mt_state ?subst_init = s_tm M"
      by (cases M) simp
    have c'_state:
      "mt_state ?c' = (s_tm M, init_offset,
                          init_buffer (le_tm M), init_dest, SS1)"
      by simp
    have pos_corr_c':
      "∀k. mt_pos ?subst_init k
              = ae_decode_pos (mt_pos ?c' k)
                              ((init_offset :: nat ⇒ 'c) k)"
      using subst_pos_zero by (simp add: ae_decode_pos_def)
    have gamma_block_c': "ae_tape_in_gamma_block M ?c'"
      unfolding ae_tape_in_gamma_block_def
      using gamma_block_init unfolding ae_tape_in_gamma_block_def
      by simp
    have simulation: "ae_simulates M ?subst_init ?c'"
      unfolding ae_simulates_def Let_def c'_state
      using qM_subst tape_corr pos_corr_c' gamma_block_c'
            s_neq_t s_neq_r by simp
    ― ‹‹buf_gamma›: SS1-landing config still carries the canonical
        ‹init_buffer (le_tm M)›; ‹init_buffer_in_gamma_block_at_M›
        discharges as in the degen case.›
    have buf_gamma_c': "ae_buffer_in_gamma_block M ?c'"
      unfolding ae_buffer_in_gamma_block_def
      using init_buffer_in_gamma_block_at_M[OF vM] by simp
    ― ‹‹le_anchor›: the SS1-landing config's tape equals
        ‹mt_tape ?init› verbatim (validation does not write the
        M'-tape); position 0 inherits ‹LE_block (le_tm M)› from
        ‹ae_init_config_tape_le›.›
    have le_anchor_c':
        "∀kk<k_tm M. mt_tape ?c' kk 0 = LE_block (le_tm M)"
      by (auto intro: ae_init_config_tape_le)
    ― ‹The validation prefix is uniquely a marker run (det-free).›
    have markers:
      "∀i<2 * length ?w + 4. ∀d.
          (?init, d) ∈ mttm_step (alphabet_enlarge_delta M) ^^ i
            ⟶ snd (snd (snd (snd (mt_state d)))) ∈ {VFwd, VFwdPad, VRet}"
      by (rule ae_validation_prefix_markers[OF vM w_sub wf s_in_Q
            s_neq_t s_neq_r le_neq_bl])
    show ?thesis
      using chain simulation buf_gamma_c' le_anchor_c' markers
      by (rule that)
  qed
qed

text ‹Noncanonical inputs reject.  The ‹bl_block bl_M ∉ set w›
  hypothesis matches ‹M'›'s input alphabet ‹Σ'›
  (‹Σ' = gamma_block (Σ_M ∪ {bl_M}) - {bl_block, LE_block}›).
  Without it, e.g.\ ‹w = [bl_block bl_M]›
  triggers ‹ae_delta_val_fwd_to_ret› at the first input
  block, mistaking it for end-of-input — validation passes
  rather than rejecting, falsifying the lemma as previously
  stated.  ‹LE_block le_M ∉ set w› follows already from
  ‹set w ⊆ gamma_block (Σ_M ∪ {bl_M})› plus
  ‹le_M ∉ Σ_M ∪ {bl_M}›, so it need not be assumed
  separately.›

lemma ae_validation_post_state_noncanonical:
  fixes M :: "('q, 'a) mttm"
    and w :: "(('c :: enum) ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and bl_notin: "bl_block (bl_tm M) ∉ set w"
      and w_bad: "¬ ae_input_well_formed (bl_tm M) w"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
  obtains n :: nat and c' where
      "n ≤ length w + 2"
    and "(ae_init_config M w, c')
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ n"
    and "case mt_state c' of (qM', _, _, _, _) ⇒ qM' = r_tm M"
proof -
  let ?init = "ae_init_config M w"
  let ?ts = "mt_tape ?init"
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have s_in_Q: "s_tm M ∈ Q_tm M" by (rule s_tm_in_Q_tm[OF vM])
  from w_bad have failure_exists:
    "∃s'. s' < length w
          ∧ ¬ is_pure_block (bl_tm M) (w ! s')
          ∧ ¬ (s' = length w - 1
               ∧ is_padded_block (bl_tm M) (w ! s'))"
    unfolding ae_input_well_formed_def by auto
  define P where
    "P = (λs'. s' < length w
               ∧ ¬ is_pure_block (bl_tm M) (w ! s')
               ∧ ¬ (s' = length w - 1
                    ∧ is_padded_block (bl_tm M) (w ! s')))"
  define s where "s = (LEAST s'. P s')"
  have failure_exists_P: "∃s'. P s'"
    using failure_exists unfolding P_def by simp
  from failure_exists_P have P_s: "P s"
    unfolding s_def by (rule LeastI_ex)
  have s_lt: "s < length w" using P_s unfolding P_def by simp
  have w_pos: "0 < length w" using s_lt by linarith
  have s_not_pure: "¬ is_pure_block (bl_tm M) (w ! s)"
    using P_s unfolding P_def by simp
  have s_not_last_padded:
    "¬ (s = length w - 1 ∧ is_padded_block (bl_tm M) (w ! s))"
    using P_s unfolding P_def by simp
  have s_min: "∀s'. P s' ⟶ s ≤ s'"
    unfolding s_def using Least_le by metis
  have pure_prefix: "∀i < s. is_pure_block (bl_tm M) (w ! i)"
  proof (intro allI impI)
    fix i assume i_lt_s: "i < s"
    have i_lt_lw: "i < length w" using i_lt_s s_lt by simp
    have i_neq_last: "i ≠ length w - 1"
      using i_lt_s s_lt w_pos by linarith
    have not_P_i: "¬ P i" using s_min i_lt_s by force
    hence "is_pure_block (bl_tm M) (w ! i)
           ∨ (i = length w - 1
              ∧ is_padded_block (bl_tm M) (w ! i))"
      using i_lt_lw unfolding P_def by auto
    thus "is_pure_block (bl_tm M) (w ! i)"
      using i_neq_last by auto
  qed
  have s_le_lw: "s ≤ length w" using s_lt by simp
  have sweep:
    "(?init,
       ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                (λi :: nat. if i = 0 then Suc s else 0))
      ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc s"
    by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t s_neq_r
                                            s_le_lw pure_prefix])
  have Sk_pos: "1 ≤ Suc s" by simp
  have Sk_le: "Suc s ≤ length w" using s_lt by simp
  have read_at_Ss: "?ts 0 (Suc s) = w ! s"
    using ae_init_config_tape_input[OF Sk_pos Sk_le kpos] by simp
  have w_s_in_set: "w ! s ∈ set w" using s_lt by auto
  have w_s_neq_bl: "w ! s ≠ bl_block (bl_tm M)"
    using w_s_in_set bl_notin by auto
  have w_s_neq_le: "w ! s ≠ LE_block (le_tm M)"
  proof (cases "le_tm M = bl_tm M")
    case True
    have eq: "LE_block (le_tm M) = bl_block (bl_tm M)"
      using True unfolding LE_block_def bl_block_def by simp
    have "w ! s ≠ bl_block (bl_tm M)" using w_s_in_set bl_notin by auto
    thus ?thesis using eq by metis
  next
    case False
    have le_notin: "le_tm M ∉ Sigma_tm M ∪ {bl_tm M}"
      using valid_mttm_LE_not_Sigma[OF vM] False by auto
    have "LE_block (le_tm M) ∉ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      using le_notin
      unfolding LE_block_def gamma_block_def by auto
    moreover have "w ! s ∈ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      using w_s_in_set w_sub by auto
    ultimately show ?thesis by auto
  qed
  have case_split: "(¬ is_canonical_block (bl_tm M) (w ! s))
                     ∨ (is_padded_block (bl_tm M) (w ! s)
                        ∧ Suc s < length w)"
  proof (cases "is_padded_block (bl_tm M) (w ! s)")
    case True
    have "s ≠ length w - 1" using s_not_last_padded True by simp
    hence "Suc s < length w" using s_lt by linarith
    thus ?thesis using True by simp
  next
    case False
    hence "¬ is_canonical_block (bl_tm M) (w ! s)"
      using s_not_pure unfolding is_canonical_block_def by simp
    thus ?thesis by simp
  qed
  consider
      (noncan) "¬ is_canonical_block (bl_tm M) (w ! s)"
    | (pad_misplaced) "is_padded_block (bl_tm M) (w ! s)"
                       "Suc s < length w"
    using case_split by blast
  thus ?thesis
  proof cases
    case noncan
    let ?n_Ss = "λi :: nat. if i = 0 then Suc s else 0"
    have read_nle: "?ts 0 (?n_Ss 0) ≠ LE_block (le_tm M)"
      using read_at_Ss w_s_neq_le by simp
    have read_nbl: "?ts 0 (?n_Ss 0) ≠ bl_block (bl_tm M)"
      using read_at_Ss w_s_neq_bl by simp
    have read_ncan: "¬ is_canonical_block (bl_tm M) (?ts 0 (?n_Ss 0))"
      using read_at_Ss noncan by simp
    have gamma: "∀kk :: nat. ?ts kk (?n_Ss kk) ∈ gamma_block (Γ_tm M)"
      using ae_init_config_in_gamma_block[OF vM w_sub] by simp
    have step_rej:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_Ss,
         ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Ss)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_fwd_reject[where ts = ?ts and n = ?n_Ss,
            OF vM s_in_Q s_neq_t s_neq_r read_nle read_nbl read_ncan
            bt_all init_stage_tail gamma buf_gamma_init])
    have stage_eq: "init_stage (le_tm M)
                    = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
      unfolding init_stage_def ..
    have step_rej_init:
      "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Ss,
         ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Ss)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_rej unfolding stage_eq by simp
    have full_chain:
      "(?init, ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Ss)
        ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc s)"
      by (rule relpow_Suc_I[OF sweep step_rej_init])
    have bound: "Suc (Suc s) ≤ length w + 2" using s_lt by linarith
    have q_eq:
      "case mt_state (ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Ss)
         of (qM', _, _, _, _) ⇒ qM' = r_tm M"
      by (simp add: init_stage_def)
    show ?thesis
      by (rule that[OF bound full_chain q_eq])
  next
    case pad_misplaced
    let ?n_Ss = "λi :: nat. if i = 0 then Suc s else 0"
    let ?n_SSs = "λi :: nat. if i = 0 then Suc (Suc s) else 0"
    have read_pad: "is_padded_block (bl_tm M) (?ts 0 (?n_Ss 0))"
      using read_at_Ss pad_misplaced(1) by simp
    have gamma_Ss: "∀kk :: nat. ?ts kk (?n_Ss kk) ∈ gamma_block (Γ_tm M)"
      using ae_init_config_in_gamma_block[OF vM w_sub] by simp
    have step_to_pad:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_Ss,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n_Ss kk)))
        ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_fwd_to_padded[where ts = ?ts and n = ?n_Ss,
            OF s_in_Q s_neq_t s_neq_r read_pad bt_all init_stage_tail
               gamma_Ss buf_gamma_init])
    have post_eq:
      "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_Ss kk))
       = ?n_SSs"
      by (rule ext) simp
    have step_to_pad_SS:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwd) ?ts ?n_Ss,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_SSs)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_to_pad post_eq by simp
    have stage_eq: "init_stage (le_tm M)
                    = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
      unfolding init_stage_def ..
    have step_to_pad_init:
      "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Ss,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_SSs)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      using step_to_pad_SS unfolding stage_eq by simp
    have SSs_pos: "1 ≤ Suc (Suc s)" by simp
    have SSs_le: "Suc (Suc s) ≤ length w"
      using pad_misplaced(2) by linarith
    have read_at_SSs: "?ts 0 (Suc (Suc s)) = w ! Suc s"
      using ae_init_config_tape_input[OF SSs_pos SSs_le kpos] by simp
    have wSs_in_set: "w ! Suc s ∈ set w"
      using SSs_le by auto
    have wSs_neq_bl: "w ! Suc s ≠ bl_block (bl_tm M)"
      using wSs_in_set bl_notin by auto
    have read_nbl_SS: "?ts 0 (?n_SSs 0) ≠ bl_block (bl_tm M)"
      using read_at_SSs wSs_neq_bl by simp
    have gamma_SS: "∀kk :: nat. ?ts kk (?n_SSs kk) ∈ gamma_block (Γ_tm M)"
      using ae_init_config_in_gamma_block[OF vM w_sub] by simp
    have step_pad_rej:
      "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_SSs,
         ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_SSs)
        ∈ mttm_step (alphabet_enlarge_delta M)"
      by (rule ae_step_val_pad_reject[where ts = ?ts and n = ?n_SSs,
            OF vM s_in_Q read_nbl_SS bt_all init_stage_tail
               gamma_SS buf_gamma_init])
    have post_sweep:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, VFwdPad) ?ts ?n_SSs)
        ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc s)"
      by (rule relpow_Suc_I[OF sweep step_to_pad_init])
    have full_chain:
      "(?init, ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_SSs)
        ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc (Suc s))"
      by (rule relpow_Suc_I[OF post_sweep step_pad_rej])
    have bound: "Suc (Suc (Suc s)) ≤ length w + 2"
      using pad_misplaced(2) by linarith
    have q_eq:
      "case mt_state (ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_SSs)
         of (qM', _, _, _, _) ⇒ qM' = r_tm M"
      by (simp add: init_stage_def)
    show ?thesis
      by (rule that[OF bound full_chain q_eq])
  qed
qed

lemma ae_validation_steps_bound:
  fixes M :: "('q, 'a) mttm"
    and w :: "('c :: enum ⇒ 'a) list"
  assumes vM: "valid_mttm M"
      and w_sub: "set w ⊆ gamma_block (Sigma_tm M ∪ {bl_tm M})"
      and s_neq_t: "s_tm M ≠ t_tm M"
      and s_neq_r: "s_tm M ≠ r_tm M"
      and le_neq_bl: "le_tm M ≠ bl_tm M"
  obtains fv :: nat and n :: nat and c' where
      "n ≤ 2 * length w + fv"
    and "(ae_init_config M w, c')
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ n"
    and "case mt_state c' of (qM', _, _, _, idx) ⇒
            idx = SS1 ∨ qM' = r_tm M"
proof -
  let ?init = "ae_init_config M w"
  let ?ts = "mt_tape ?init"
  have kpos: "0 < k_tm M" by (rule valid_mttm_k_pos[OF vM])
  have bt_all: "∀j≥k_tm M. ∀i. ?ts j i = bl_block (bl_tm M)"
    using ae_init_config_tape_blank_tail by blast
  have buf_gamma_init:
      "∀kk :: nat.
          fst (init_buffer (le_tm M) kk
                  :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a))
              ∈ gamma_block (Γ_tm M)
          ∧ fst (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)
          ∧ snd (snd (init_buffer (le_tm M) kk
                        :: ('c ⇒ 'a) × ('c ⇒ 'a) × ('c ⇒ 'a)))
              ∈ gamma_block (Γ_tm M)"
    by (rule init_buffer_in_gamma_block_at_M[OF vM])
  have s_in_Q: "s_tm M ∈ Q_tm M" by (rule s_tm_in_Q_tm[OF vM])
  consider
      (no_bl_wf)
        "bl_block (bl_tm M) ∉ set w" "ae_input_well_formed (bl_tm M) w"
    | (no_bl_nwf)
        "bl_block (bl_tm M) ∉ set w" "¬ ae_input_well_formed (bl_tm M) w"
    | (has_bl)
        "bl_block (bl_tm M) ∈ set w"
    by blast
  thus ?thesis
  proof cases
    case no_bl_nwf
    obtain n c' where
        bound: "n ≤ length w + 2"
      and chain: "(ae_init_config M w, c')
                    ∈ mttm_step (alphabet_enlarge_delta M) ^^ n"
      and state_eq: "case mt_state c' of (qM', _, _, _, _) ⇒ qM' = r_tm M"
      using ae_validation_post_state_noncanonical[OF vM w_sub
              no_bl_nwf(1) no_bl_nwf(2) s_neq_t s_neq_r] by metis
    have bound2: "n ≤ 2 * length w + 4" using bound by linarith
    have state_eq_disj: "case mt_state c'
            of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
      using state_eq by (cases "mt_state c'") auto
    show ?thesis using bound2 chain state_eq_disj by (rule that)
  next
    case no_bl_wf
    have wf: "ae_input_well_formed (bl_tm M) w" using no_bl_wf(2) .
    have full_chain:
      "(?init,
         ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                    init_dest, SS1) ?ts (λ_. 0))
          ∈ mttm_step (alphabet_enlarge_delta M)
              ^^ (2 * length w + 4)"
      by (rule ae_validation_well_formed_to_SS1[OF vM w_sub wf s_in_Q
            s_neq_t s_neq_r le_neq_bl])
    have bound: "(2 * length w + 4 :: nat) ≤ 2 * length w + 4" by simp
    have state_eq:
      "case mt_state (ConfigM (s_tm M, init_offset,
                                     init_buffer (le_tm M),
                                     init_dest, SS1) ?ts (λ_. 0))
          of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
      by simp
    show ?thesis by (rule that[OF bound full_chain state_eq])
  next
    case has_bl
    have LE_neq_bl_block: "LE_block (le_tm M) ≠ bl_block (bl_tm M)"
      using le_neq_bl unfolding LE_block_def bl_block_def
      by (metis fun_eq_iff)
    have tape_le: "?ts (0 :: nat) 0 = LE_block (le_tm M)"
      by (rule ae_init_config_tape_le[OF kpos])
    have gamma_all: "∀k i. ?ts k i ∈ gamma_block (Γ_tm M)"
      using ae_init_config_in_gamma_block[OF vM w_sub] by simp
    have stage_eq: "init_stage (le_tm M)
                    = (init_offset, init_buffer (le_tm M), init_dest, VFwd)"
      unfolding init_stage_def ..
    ― ‹Show ‹LE_block le_M ∉ set w›: in the ‹le ≠ bl›
        regime, ‹le ∉ Σ ∪ {bl}› forces ‹LE_block› out of
        ‹gamma_block›.›
    have LE_notin: "LE_block (le_tm M) ∉ set w"
    proof -
      have le_notin: "le_tm M ∉ Sigma_tm M ∪ {bl_tm M}"
        using valid_mttm_LE_not_Sigma[OF vM] le_neq_bl by auto
      have "LE_block (le_tm M) ∉ gamma_block (Sigma_tm M ∪ {bl_tm M})"
        using le_notin
        unfolding LE_block_def gamma_block_def by auto
      thus ?thesis using w_sub by auto
    qed
    ― ‹Find the first non-pure index — well-defined because
        ‹bl_block› is non-pure and present somewhere in ‹w›.›
    define P where
      "P = (λi. i < length w ∧ ¬ is_pure_block (bl_tm M) (w ! i))"
    have ex_P: "∃i. P i"
    proof -
      from has_bl obtain j where j_lt: "j < length w" and j_eq: "w ! j = bl_block (bl_tm M)"
        by (auto simp: in_set_conv_nth)
      have "¬ is_pure_block (bl_tm M) (bl_block (bl_tm M))"
        unfolding is_pure_block_def bl_block_def by auto
      hence "¬ is_pure_block (bl_tm M) (w ! j)" using j_eq by simp
      thus ?thesis unfolding P_def using j_lt by auto
    qed
    define k where "k = (LEAST i. P i)"
    from ex_P have P_k: "P k" unfolding k_def by (rule LeastI_ex)
    have k_lt: "k < length w" using P_k unfolding P_def by simp
    have k_not_pure: "¬ is_pure_block (bl_tm M) (w ! k)"
      using P_k unfolding P_def by simp
    have k_min: "∀j. P j ⟶ k ≤ j"
      unfolding k_def using Least_le by metis
    have pure_prefix: "∀i < k. is_pure_block (bl_tm M) (w ! i)"
    proof (intro allI impI)
      fix i assume i_lt_k: "i < k"
      have i_lt_w: "i < length w" using i_lt_k k_lt by simp
      have "¬ P i" using k_min i_lt_k by force
      thus "is_pure_block (bl_tm M) (w ! i)" unfolding P_def using i_lt_w by auto
    qed
    have k_le_lw: "k ≤ length w" using k_lt by simp
    have sweep:
      "(?init,
          ConfigM (s_tm M, init_stage (le_tm M)) ?ts
                   (λi :: nat. if i = 0 then Suc k else 0))
          ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc k"
      by (rule ae_validation_fwd_sweep_pure[OF vM w_sub s_in_Q s_neq_t
                                              s_neq_r k_le_lw pure_prefix])
    let ?n_Sk = "λi :: nat. if i = 0 then Suc k else 0"
    have Sk_pos: "1 ≤ Suc k" by simp
    have Sk_le: "Suc k ≤ length w" using k_lt by simp
    have read_at_Sk: "?ts 0 (Suc k) = w ! k"
      using ae_init_config_tape_input[OF Sk_pos Sk_le kpos] by simp
    have w_k_in_set: "w ! k ∈ set w" using k_lt by auto
    have w_k_neq_le: "w ! k ≠ LE_block (le_tm M)"
      using w_k_in_set LE_notin by auto
    ― ‹Case-split on ‹w!k›: ‹bl_block› (passes), padded
        (sub-case on next), or non-canonical (rejects).›
    consider
        (case_bl) "w ! k = bl_block (bl_tm M)"
      | (case_pad) "is_padded_block (bl_tm M) (w ! k)"
      | (case_noncan) "¬ is_canonical_block (bl_tm M) (w ! k)"
                       "w ! k ≠ bl_block (bl_tm M)"
      using k_not_pure unfolding is_canonical_block_def by blast
    thus ?thesis
    proof cases
      case case_bl
      ― ‹Forward sweep + ‹fwd_to_ret› + return sweep, ending at SS1.›
      have read_bl: "?ts 0 (?n_Sk 0) = bl_block (bl_tm M)"
        using read_at_Sk case_bl by simp
      have gamma_Sk:
        "∀kk :: nat. ?ts kk (?n_Sk kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_to_ret:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VRet) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        by (rule ae_step_val_fwd_to_ret[where ts = ?ts and n = ?n_Sk,
              OF s_in_Q s_neq_t s_neq_r read_bl bt_all init_stage_tail
                 gamma_Sk buf_gamma_init])
      have step_to_ret_init:
        "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VRet) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        using step_to_ret unfolding stage_eq by simp
      have post_sweep:
        "(?init,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VRet) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc k)"
        by (rule relpow_Suc_I[OF sweep step_to_ret_init])
      have non_le_Sk: "∀i. 1 ≤ i ∧ i ≤ Suc k
                          ⟶ ?ts 0 i ≠ LE_block (le_tm M)"
      proof (intro allI impI)
        fix i assume i_range: "1 ≤ i ∧ i ≤ Suc k"
        have i_pos: "1 ≤ i" using i_range by simp
        have i_le_lw: "i ≤ length w" using i_range Sk_le by linarith
        have eq: "?ts 0 i = w ! (i - 1)"
          using ae_init_config_tape_input[OF i_pos i_le_lw kpos] by simp
        have "w ! (i - 1) ∈ set w" using i_pos i_le_lw by auto
        thus "?ts 0 i ≠ LE_block (le_tm M)" using LE_notin eq by auto
      qed
      have ret_arrow:
        "(∀i. 1 ≤ i ∧ i ≤ Suc k
              ⟶ ?ts 0 i ≠ LE_block (le_tm M))
         ⟶ (ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                          init_dest, VRet) ?ts ?n_Sk,
              ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                          init_dest, SS1) ?ts (λ_. 0))
              ∈ mttm_step (alphabet_enlarge_delta M)
                  ^^ Suc (Suc k)"
        by (rule ae_validation_ret_sweep[OF s_in_Q tape_le gamma_all
                                          buf_gamma_init bt_all init_stage_tail])
      have ret_chain:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VRet) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ Suc (Suc k)"
        using ret_arrow non_le_Sk by (rule mp)
      have full_chain_pre:
        "(?init,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, SS1) ?ts (λ_. 0))
            ∈ mttm_step (alphabet_enlarge_delta M)
                ^^ (Suc (Suc k) + Suc (Suc k))"
      proof -
        have comp:
          "(?init,
             ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, SS1) ?ts (λ_. 0))
              ∈ mttm_step (alphabet_enlarge_delta M)
                  ^^ Suc (Suc k)
                O mttm_step (alphabet_enlarge_delta M)
                  ^^ Suc (Suc k)"
          using post_sweep ret_chain by (rule relcompI)
        thus ?thesis by (simp only: relpow_add)
      qed
      have bound: "Suc (Suc k) + Suc (Suc k) ≤ 2 * length w + 4"
        using k_lt by linarith
      have state_eq:
        "case mt_state (ConfigM (s_tm M, init_offset,
                                       init_buffer (le_tm M),
                                       init_dest, SS1) ?ts (λ_. 0))
            of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
        by simp
      show ?thesis by (rule that[OF bound full_chain_pre state_eq])
    next
      case case_pad
      ― ‹In ‹has_bl› + first-non-pure-padded, the ‹bl_block› must
          appear at some position ‹j > k›, hence ‹Suc k < length
          w›.›
      have Sk_lt: "Suc k < length w"
      proof -
        from has_bl obtain j where j_lt: "j < length w"
              and j_eq: "w ! j = bl_block (bl_tm M)" by (auto simp: in_set_conv_nth)
        have "j ≥ k"
        proof (rule ccontr)
          assume "¬ j ≥ k"
          hence "j < k" by simp
          hence "is_pure_block (bl_tm M) (w ! j)" using pure_prefix by simp
          moreover have "¬ is_pure_block (bl_tm M) (bl_block (bl_tm M))"
            unfolding is_pure_block_def bl_block_def by auto
          ultimately show False using j_eq by auto
        qed
        moreover have "j ≠ k"
        proof
          assume "j = k"
          hence wk_bl: "w ! k = bl_block (bl_tm M)" using j_eq by simp
          have not_padded:
            "¬ is_padded_block (bl_tm M) ((bl_block (bl_tm M)) :: 'c ⇒ 'a)"
          proof
            assume "is_padded_block (bl_tm M)
                    ((bl_block (bl_tm M)) :: 'c ⇒ 'a)"
            then obtain k_pad where
                k_pad_pos: "k_pad ≥ 1"
              and k_pad_lt: "k_pad < length (enum_class.enum :: 'c list)"
              and prefix_cond:
                "∀x. c_idx x < k_pad
                      ⟶ ((bl_block (bl_tm M)) :: 'c ⇒ 'a) x ≠ bl_tm M"
              unfolding is_padded_block_def by blast
            have len_pos: "0 < length (enum_class.enum :: 'c list)"
              using k_pad_lt k_pad_pos by linarith
            have "c_idx ((enum_class.enum :: 'c list) ! 0) = 0"
              by (rule c_idx_enum_nth[OF len_pos])
            hence c_first_idx: "c_idx (c_first :: 'c) = 0"
              unfolding c_first_def .
            hence "c_idx (c_first :: 'c) < k_pad"
              using k_pad_pos by simp
            hence "(bl_block (bl_tm M) :: 'c ⇒ 'a) c_first ≠ bl_tm M"
              using prefix_cond by blast
            thus False unfolding bl_block_def by simp
          qed
          show False using case_pad wk_bl not_padded by simp
        qed
        ultimately have "j > k" by simp
        thus ?thesis using j_lt by linarith
      qed
      let ?n_SSk = "λi :: nat. if i = 0 then Suc (Suc k) else 0"
      have read_pad: "is_padded_block (bl_tm M) (?ts 0 (?n_Sk 0))"
        using read_at_Sk case_pad by simp
      have gamma_Sk:
        "∀kk :: nat. ?ts kk (?n_Sk kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_to_pad:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts
                  (λkk. go_dir (if kk = (0 :: nat) then dir.R else dir.N)
                                 (?n_Sk kk)))
            ∈ mttm_step (alphabet_enlarge_delta M)"
        by (rule ae_step_val_fwd_to_padded[where ts = ?ts and n = ?n_Sk,
              OF s_in_Q s_neq_t s_neq_r read_pad bt_all init_stage_tail
                 gamma_Sk buf_gamma_init])
      have post_eq_pad:
        "(λkk :: nat. go_dir (if kk = 0 then dir.R else dir.N) (?n_Sk kk))
         = ?n_SSk"
        by (rule ext) simp
      have step_to_pad_norm:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts ?n_SSk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        using step_to_pad post_eq_pad by simp
      have step_to_pad_init:
        "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Sk,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts ?n_SSk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        using step_to_pad_norm unfolding stage_eq by simp
      have post_sweep_VFwdPad:
        "(?init,
           ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwdPad) ?ts ?n_SSk)
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc k)"
        by (rule relpow_Suc_I[OF sweep step_to_pad_init])
      have SSk_pos: "1 ≤ Suc (Suc k)" by simp
      have SSk_le: "Suc (Suc k) ≤ length w" using Sk_lt by linarith
      have read_at_SSk: "?ts 0 (Suc (Suc k)) = w ! Suc k"
        using ae_init_config_tape_input[OF SSk_pos SSk_le kpos] by simp
      have wSk_in_set: "w ! Suc k ∈ set w" using SSk_le by auto
      have gamma_SSk:
        "∀kk :: nat. ?ts kk (?n_SSk kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      ― ‹Sub-case on ‹w ! Suc k›: ‹bl_block› (passes via
          ‹pad_to_ret›) or non-‹bl_block› (rejects via ‹pad_reject›).›
      consider
          (pad_pass) "w ! Suc k = bl_block (bl_tm M)"
        | (pad_reject) "w ! Suc k ≠ bl_block (bl_tm M)"
        by blast
      thus ?thesis
      proof cases
        case pad_pass
        have read_bl_SSk: "?ts 0 (?n_SSk 0) = bl_block (bl_tm M)"
          using read_at_SSk pad_pass by simp
        have step_pad_to_ret:
          "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VFwdPad) ?ts ?n_SSk,
             ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VRet) ?ts ?n_SSk)
              ∈ mttm_step (alphabet_enlarge_delta M)"
          by (rule ae_step_val_pad_to_ret[where ts = ?ts and n = ?n_SSk,
                OF s_in_Q read_bl_SSk bt_all init_stage_tail
                   gamma_SSk buf_gamma_init])
        have post_sweep_VRet:
          "(?init,
             ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VRet) ?ts ?n_SSk)
              ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc (Suc k))"
          by (rule relpow_Suc_I[OF post_sweep_VFwdPad step_pad_to_ret])
        have non_le_SSk: "∀i. 1 ≤ i ∧ i ≤ Suc (Suc k)
                              ⟶ ?ts 0 i ≠ LE_block (le_tm M)"
        proof (intro allI impI)
          fix i assume i_range: "1 ≤ i ∧ i ≤ Suc (Suc k)"
          have i_pos: "1 ≤ i" using i_range by simp
          have i_le_lw: "i ≤ length w" using i_range SSk_le by linarith
          have eq: "?ts 0 i = w ! (i - 1)"
            using ae_init_config_tape_input[OF i_pos i_le_lw kpos] by simp
          have "w ! (i - 1) ∈ set w" using i_pos i_le_lw by auto
          thus "?ts 0 i ≠ LE_block (le_tm M)" using LE_notin eq by auto
        qed
        have ret_arrow:
          "(∀i. 1 ≤ i ∧ i ≤ Suc (Suc k)
                ⟶ ?ts 0 i ≠ LE_block (le_tm M))
           ⟶ (ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, VRet) ?ts ?n_SSk,
                ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                            init_dest, SS1) ?ts (λ_. 0))
                ∈ mttm_step (alphabet_enlarge_delta M)
                    ^^ Suc (Suc (Suc k))"
          by (rule ae_validation_ret_sweep[OF s_in_Q tape_le gamma_all
                                          buf_gamma_init bt_all init_stage_tail])
        have ret_chain:
          "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VRet) ?ts ?n_SSk,
             ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, SS1) ?ts (λ_. 0))
              ∈ mttm_step (alphabet_enlarge_delta M)
                  ^^ Suc (Suc (Suc k))"
          using ret_arrow non_le_SSk by (rule mp)
        have full_chain:
          "(?init,
             ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, SS1) ?ts (λ_. 0))
              ∈ mttm_step (alphabet_enlarge_delta M)
                  ^^ (Suc (Suc (Suc k)) + Suc (Suc (Suc k)))"
        proof -
          have comp:
            "(?init,
               ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                          init_dest, SS1) ?ts (λ_. 0))
                ∈ mttm_step (alphabet_enlarge_delta M)
                    ^^ Suc (Suc (Suc k))
                  O mttm_step (alphabet_enlarge_delta M)
                    ^^ Suc (Suc (Suc k))"
            using post_sweep_VRet ret_chain by (rule relcompI)
          thus ?thesis by (simp only: relpow_add)
        qed
        have bound:
          "Suc (Suc (Suc k)) + Suc (Suc (Suc k)) ≤ 2 * length w + 4"
          using Sk_lt by linarith
        have state_eq:
          "case mt_state (ConfigM (s_tm M, init_offset,
                                         init_buffer (le_tm M),
                                         init_dest, SS1) ?ts (λ_. 0))
              of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
          by simp
        show ?thesis by (rule that[OF bound full_chain state_eq])
      next
        case pad_reject
        have read_nbl_SSk: "?ts 0 (?n_SSk 0) ≠ bl_block (bl_tm M)"
          using read_at_SSk pad_reject by simp
        have step_pad_rej:
          "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                        init_dest, VFwdPad) ?ts ?n_SSk,
             ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_SSk)
              ∈ mttm_step (alphabet_enlarge_delta M)"
          by (rule ae_step_val_pad_reject[where ts = ?ts and n = ?n_SSk,
                OF vM s_in_Q read_nbl_SSk bt_all init_stage_tail
                   gamma_SSk buf_gamma_init])
        have full_chain:
          "(?init, ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_SSk)
              ∈ mttm_step (alphabet_enlarge_delta M)
                  ^^ Suc (Suc (Suc k))"
          by (rule relpow_Suc_I[OF post_sweep_VFwdPad step_pad_rej])
        have bound: "Suc (Suc (Suc k)) ≤ 2 * length w + 4"
          using Sk_lt by linarith
        have state_eq:
          "case mt_state (ConfigM (r_tm M, init_stage (le_tm M))
                                       ?ts ?n_SSk)
              of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
          by (simp add: init_stage_def)
        show ?thesis by (rule that[OF bound full_chain state_eq])
      qed
    next
      case case_noncan
      have read_nle: "?ts 0 (?n_Sk 0) ≠ LE_block (le_tm M)"
        using read_at_Sk w_k_neq_le by simp
      have read_nbl: "?ts 0 (?n_Sk 0) ≠ bl_block (bl_tm M)"
        using read_at_Sk case_noncan(2) by simp
      have read_ncan: "¬ is_canonical_block (bl_tm M) (?ts 0 (?n_Sk 0))"
        using read_at_Sk case_noncan(1) by simp
      have gamma_Sk:
        "∀kk :: nat. ?ts kk (?n_Sk kk) ∈ gamma_block (Γ_tm M)"
        using gamma_all by simp
      have step_rej:
        "(ConfigM (s_tm M, init_offset, init_buffer (le_tm M),
                      init_dest, VFwd) ?ts ?n_Sk,
           ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        by (rule ae_step_val_fwd_reject[where ts = ?ts and n = ?n_Sk,
              OF vM s_in_Q s_neq_t s_neq_r read_nle read_nbl read_ncan
              bt_all init_stage_tail gamma_Sk buf_gamma_init])
      have step_rej_init:
        "(ConfigM (s_tm M, init_stage (le_tm M)) ?ts ?n_Sk,
           ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M)"
        using step_rej unfolding stage_eq by simp
      have full_chain:
        "(?init, ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Sk)
            ∈ mttm_step (alphabet_enlarge_delta M) ^^ Suc (Suc k)"
        by (rule relpow_Suc_I[OF sweep step_rej_init])
      have bound: "Suc (Suc k) ≤ 2 * length w + 4" using k_lt by linarith
      have state_eq:
        "case mt_state (ConfigM (r_tm M, init_stage (le_tm M)) ?ts ?n_Sk)
            of (qM', _, _, _, idx) ⇒ idx = SS1 ∨ qM' = r_tm M"
        by (simp add: init_stage_def)
      show ?thesis by (rule that[OF bound full_chain state_eq])
    qed
  qed
qed

end