Theory Multitape_Alphabet_Enlargement.AlphabetEnlargement_Acceptance

theory AlphabetEnlargement_Acceptance
  imports AlphabetEnlargement_ForwardStage
begin

subsection ‹Acceptance correspondence and step-count engine›

subsubsection ‹Acceptance correspondence and initial setup›

text ‹Acceptance correspondence: M› accepts iff M'›'s
  state equals the canonical M'›-accept config
  (t_tm M, init_stage le_M)›.  Direct from
  ae_simulates_def›'s XOR-style halt-arm disjunct (which pins
  down (off, buf, dest, idx) = init_stage le_M› exactly when
  qM' ∈ {t_tm M, r_tm M}›) plus the q›-correspondence
  conjunct.›

lemma ae_simulates_accept_iff:
  fixes M :: "('q, 'a) mttm"
    and cM :: "('a, 'q) mt_config"
    and c' :: "('c :: enum  'a,
                'q × ('a, 'c) ae_stage) mt_config"
  assumes vM:  "valid_mttm M"
      and sim: "ae_simulates M cM c'"
    shows "(mt_state cM = t_tm M)
             (mt_state c' = (t_tm M, init_stage (le_tm M)))"
proof -
  obtain qM' ofs buf dest idx where
      state_comp: "mt_state c' = (qM', ofs, buf, dest, idx)"
    by (cases "mt_state c'")
  have sim_body:
      "((idx = SS1  qM'  {t_tm M, r_tm M})
           (qM'  {t_tm M, r_tm M}
                (ofs, buf, dest, idx) = init_stage (le_tm M)))
        mt_state cM = qM'
        (k<k_tm M. ae_tape_correspondence (le_tm M)
                 (mt_tape cM k) (mt_tape c' k))
        (idx = SS1
             (k<k_tm M. mt_pos cM k = ae_decode_pos (mt_pos c' k) (ofs k)))
        ae_tape_in_gamma_block M c'"
    using sim state_comp unfolding ae_simulates_def by simp
  have disj:
      "(idx = SS1  qM'  {t_tm M, r_tm M})
         (qM'  {t_tm M, r_tm M}
              (ofs, buf, dest, idx) = init_stage (le_tm M))"
    using sim_body by simp
  have qM_eq: "mt_state cM = qM'" using sim_body by simp
  show ?thesis
  proof
    assume hyp: "mt_state cM = t_tm M"
    hence qM'_eq_t: "qM' = t_tm M" using qM_eq by simp
    hence q_in_halt: "qM'  {t_tm M, r_tm M}" by simp
    have shape: "(ofs, buf, dest, idx) = init_stage (le_tm M)"
      using disj q_in_halt by auto
    show "mt_state c' = (t_tm M, init_stage (le_tm M))"
      using state_comp qM'_eq_t shape by simp
  next
    assume "mt_state c' = (t_tm M, init_stage (le_tm M))"
    hence "qM' = t_tm M" using state_comp by simp
    thus "mt_state cM = t_tm M" using qM_eq by simp
  qed
qed

text ‹Initial setup: post-validation, the simulation holds
  between M›'s initial config on u› and M'›'s
  post-validation config on encode_input (bl_tm M) u›.
  Combines ae_validation_post_state_canonical› with the
  encoder's correctness.›

lemma ae_init_config_simulates_post_validation:
  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 -
  obtain n c' where
      A: "(ae_init_config M (encode_input (bl_tm M) u), c')
             mttm_step (alphabet_enlarge_delta M) ^^ n"
    and B: "ae_simulates M
              (init_config_mttm M u)
              (c' :: ('c  'a,
                      'q × ('a, 'c) ae_stage) mt_config)"
    and C: "ae_buffer_in_gamma_block M c'"
    and D: "kk<k_tm M. mt_tape c' kk 0 = LE_block (le_tm M)"
    and E: "i<n. d :: ('c  '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}"
    by (rule ae_validation_post_state_canonical[OF vM u_sub le_neq_bl])
  show ?thesis using A B C D E by (rule that)
qed

subsubsection ‹Step-count machinery and chunked simulation engine›

text ‹Step-counting lemmas: validation phase bounded by
  2 ⋅ n + fv; simulation phase bounded by
  8 ⋅ ⌈T(c ⋅ n) / c⌉›.›

text ‹This is the general-input form of the validation-phase
  step count: for any well-formed AE-input w›, the
  validation phase completes in O(|w|)› steps and lands
  either at the canonical SS1 configuration or in the reject
  state.  It is not invoked by the headline time theorem
  alphabet_enlarge_time› below — for canonical
  encoder-image inputs that the base machine accepts, the
  narrower form ae_validation_well_formed_to_SS1› in
  theory AlphabetEnlargement_ValidationBound› gives the exact step
  count 2 ⋅ |w| + 4› with SS1 as the only outcome,
  which is what the linear-speedup proof needs.  The general
  form is retained as a structural completeness result
  describing the AE machine's runtime behaviour on
  non-canonical or rejected inputs — of potential use for
  downstream consumers that reason about reject paths, and for
  the nondeterministic-reverse research thread.›

lemma ae_validation_phase_step_count:
  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 -
  obtain fv n c' where
      A: "n  2 * length w + fv"
    and B: "(ae_init_config M w, c')
               mttm_step (alphabet_enlarge_delta M) ^^ n"
    and C: "case mt_state c' of (qM', _, _, _, idx) 
              idx = SS1  qM' = r_tm M"
    using ae_validation_steps_bound[OF vM w_sub s_neq_t s_neq_r le_neq_bl]
    by metis
  show ?thesis using A B C by (rule that)
qed

text ‹Chunked-induction engine for the simulation-phase
  step count.  Given a specific (finite) accepting M›-path
  of length n› from a reachable cM› with a paired SS1
  M'-config c'› satisfying the invariants buf_gamma›,
  le_anchor›, exhibit a corresponding accepting M'›-path
  of length at most 8 ⋅ ⌈n / c⌉›.

  Proof structure (when discharged): induction on the M-path
  length n›, taking the next chunk of up to
  c = card (UNIV :: 'c set)› M-steps per stage and
  invoking ae_simulates_forward_stage_general›.  The
  invariant buf_gamma c'_j ∧ le_anchor c'_j› is
  preserved by forward_stage_general›'s output
  conjuncts (just strengthened in the previous commit).  The
  M-side no_le_per_tape› hypothesis for the per-tape
  unified forward stage is discharged from
  valid_reach_LE_only_pos0_mttm› on the substrate,
  threaded through reach_M›.

  Wrapped by ae_simulation_phase_step_count› below to
  produce the named-bound obtains›-form.›

lemma ae_simulation_phase_chunked:
  fixes M :: "('q, 'a) mttm"
    and w :: "'a list"
    and cM cM_final :: "('a, 'q) mt_config"
    and c' :: "('c :: enum  'a,
                'q × ('a, 'c) ae_stage) mt_config"
    and n :: nat
  assumes vM:         "valid_mttm M"
      and lu:         "le_unique M"
      and w_sub:      "set w  Sigma_tm M"
      and le_neq_bl:  "le_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 reach_M:    "(init_config_mttm M w, cM)
                           (mttm_step (delta_tm M))*"
      and trace:      "(cM, cM_final)  (mttm_step (delta_tm M))^^n"
      and accept:     "mt_state cM_final = t_tm M"
      and sim:        "ae_simulates M cM c'"
      and buf_gamma:  "ae_buffer_in_gamma_block M c'"
      and le_anchor:  "kk<k_tm M. mt_tape c' kk 0 = LE_block (le_tm M)"
  shows "m c''. m  8 * ((n + card (UNIV :: 'c set) - 1)
                            div card (UNIV :: 'c set))
               (c', c'')  (mttm_step (alphabet_enlarge_delta M))^^m
               mt_state c'' = (t_tm M, init_stage (le_tm M))"
  using reach_M trace accept sim buf_gamma le_anchor
proof (induction n arbitrary: cM cM_final c' rule: less_induct)
  case (less n)
  ― ‹Strong-induction case for path-length n›.  The hypotheses
      reach_M›, trace›, accept›, sim›, buf_gamma›,
      le_anchor› have been re-quantified over cM›,
      cM_final›, c'› by the induction; less.prems›
      restates them for this n›, and less.IH› gives the
      conclusion for every strictly smaller n'› (with its
      own fresh cM'›, cM_final'›, c''›).›
  show ?case
  proof (cases n)
    case 0
    ― ‹Base case: n = 0› means cM = cM_final› (length-0
        trace), so mt_state cM = t_tm M› by accept›.
        ae_simulates_accept_iff› then forces
        mt_state c' = (t_tm M, init_stage (le_tm M))›.
        Witness: m = 0›, c'' = c'›.›
    have trace_zero: "(cM, cM_final)  (mttm_step (delta_tm M))^^0"
      using less.prems(2) n = 0 by simp
    have cM_eq: "cM_final = cM"
      using trace_zero by simp
    have mt_cM: "mt_state cM = t_tm M"
      using less.prems(3) cM_eq by simp
    have state_c': "mt_state c' = (t_tm M, init_stage (le_tm M))"
      using ae_simulates_accept_iff[OF vM less.prems(4)] mt_cM by simp
    have run_zero:
        "(c', c')  (mttm_step (alphabet_enlarge_delta M))^^0"
      by simp
    have bound_zero:
        "(0 :: nat)  8 * ((n + card (UNIV :: 'c set) - 1)
                             div card (UNIV :: 'c set))"
      by simp
    show ?thesis
      using bound_zero run_zero state_c' by blast
  next
    case (Suc n_minus_1)
    ― ‹Inductive case: n > 0›.  Select the chunk size
        k_chunk ≤ c›: the earliest halt index in
        [1..min n c]›, or c› if no halt in that range.
        Split the trace as cM →k_chunk cM_k →(n - k_chunk)
        cM_final›; apply forward_stage_general› to get an
        M'-witness for the first chunk; apply less.IH›
        on n - k_chunk < n› for the remaining trace.›
    ― ‹Substep A: extract the first M-step from the
        non-empty trace and derive cM›'s status
        (non-halt, in Q) from mttm_step_src›.›
    have trace_Suc: "(cM, cM_final)
                        mttm_step (delta_tm M) ^^ Suc n_minus_1"
      using less.prems(2) Suc by simp
    obtain cM_1 where
        step_first: "(cM, cM_1)  mttm_step (delta_tm M)"
      and rest_trace: "(cM_1, cM_final)
                           mttm_step (delta_tm M) ^^ n_minus_1"
      using relpow_Suc_D2[OF trace_Suc] by blast
    have cM_in_Q:  "mt_state cM  Q_tm M"
      using mttm_step_src_in_Q[OF vM step_first] .
    have cM_neq_t: "mt_state cM  t_tm M"
      using mttm_step_src_neq_t[OF vM step_first] .
    have cM_neq_r: "mt_state cM  r_tm M"
      using mttm_step_src_neq_r[OF vM step_first] .
    ― ‹Substep B: name the alphabet-grouping size c› and
        define the chunk size as k_chunk = min n c›.  Since
        the universal-form prefix_nhalt› hypothesis has been
        retired from forward_stage_general› (the AE-chain
        audit found it was dead weight propagated through every
        layer without being used substantively), the chunk just
        needs to satisfy end_or_halt›, which holds via
        k_chunk = n = halt› when n ≤ c›, or via
        k_chunk = c› when n > c›.›
    define c where "c  card (UNIV :: 'c set)"
    have c_pos: "0 < c"
    proof -
      have "(c_first :: 'c)  UNIV" by simp
      thus ?thesis unfolding c_def by (simp add: card_gt_0_iff)
    qed
    define k_chunk where "k_chunk  min n c"
    have k_chunk_pos:  "0 < k_chunk"
      using c_pos Suc unfolding k_chunk_def by simp
    have k_chunk_le_n: "k_chunk  n"
      unfolding k_chunk_def by simp
    have k_chunk_le_c: "k_chunk  c"
      unfolding k_chunk_def by simp
    have k_chunk_lt_n_or_eq_n: "k_chunk < n  k_chunk = n"
      using k_chunk_le_n by linarith
    ― ‹Substep C: split the M-trace at k_chunk›.  Since
        k_chunk ≤ n›, k_chunk + (n - k_chunk) = n›;
        relpow_add› turns rel ^^ n› into the composition
        rel ^^ k_chunk O rel ^^ (n - k_chunk)›, which a single
        unpacking exposes cM_k›.›
    have trace_split_rel:
        "(cM, cM_final)  (mttm_step (delta_tm M) ^^ k_chunk)
                           O (mttm_step (delta_tm M) ^^ (n - k_chunk))"
    proof -
      have sum_eq: "k_chunk + (n - k_chunk) = n"
        using k_chunk_le_n by simp
      have "(cM, cM_final)  mttm_step (delta_tm M)
                                ^^ (k_chunk + (n - k_chunk))"
        using less.prems(2) sum_eq by simp
      thus ?thesis by (simp add: relpow_add)
    qed
    obtain cM_k where
        chunk_trace: "(cM, cM_k)  mttm_step (delta_tm M) ^^ k_chunk"
      and rest_after_chunk:
          "(cM_k, cM_final)  mttm_step (delta_tm M) ^^ (n - k_chunk)"
      using trace_split_rel by auto
    ― ‹Substep E: end_or_halt›.  Two cases:
          - k_chunk = n›: n ≤ c›, cM_k = cM_final›
            (from length-zero remaining trace), state is t_tm M›
            by accept›.  Second disjunct fires.
          - k_chunk < n›: n > c›, so min n c = c›, i.e.,
            k_chunk = c›.  First disjunct fires.›
    have end_or_halt:
        "k_chunk = c  mt_state cM_k  {t_tm M, r_tm M}"
    proof (cases "k_chunk = n")
      case True
      hence "n - k_chunk = 0" by simp
      hence "cM_k = cM_final"
        using rest_after_chunk by simp
      hence "mt_state cM_k = t_tm M"
        using less.prems(3) by simp
      thus ?thesis by simp
    next
      case False
      hence "k_chunk < n" using k_chunk_le_n by linarith
      hence "min n c < n" unfolding k_chunk_def by simp
      hence "c < n" by linarith
      hence "min n c = c" by simp
      hence "k_chunk = c" unfolding k_chunk_def by simp
      thus ?thesis by simp
    qed
    ― ‹Substep F: derive no_le_per_tape› for cM› from
        substrate reachability.  Each disjunct of
        no_le_per_tape› asserts that an M›-tape cell at some
        positive index is not the left-end marker.  The substrate
        lemma valid_reach_LE_only_pos0_mttm› exactly delivers
        this for every cell index p ≠ 0› along a reachable
        trace from init_config_mttm M w›; the three disjuncts'
        cell indices ((mt_pos c' kk - 2) * c + 1 + i› and
        Suc i› twice) are all syntactically positive, so the
        p ≠ 0› obligation is discharged by by simp›.›
    have reach_cM: "(init_config_mttm M w, cM)
                        (mttm_step (delta_tm M))*"
      using less.prems(1) .
    have no_le_per_tape:
        "kk. (mt_pos c' kk  2
                 (i. i < 3 * c
                           mt_tape cM kk
                                ((mt_pos c' kk - 2) * c + 1 + i)
                               le_tm M))
              (mt_pos c' kk = 1
                   (i. i < 2 * c
                             mt_tape cM kk (Suc i)  le_tm M))
              (mt_pos c' kk = 0
                   (i. i < c
                             mt_tape cM kk (Suc i)  le_tm M))"
    proof (intro allI conjI impI allI impI)
      fix kk :: nat and i :: nat
      assume "2  mt_pos c' kk" and "i < 3 * c"
      have idx_nz: "(mt_pos c' kk - 2) * c + 1 + i  0" by simp
      show "mt_tape cM kk ((mt_pos c' kk - 2) * c + 1 + i)  le_tm M"
        using valid_reach_LE_only_pos0_mttm
                [OF vM lu w_sub reach_cM idx_nz le_neq_bl[symmetric]] .
    next
      fix kk :: nat and i :: nat
      assume "mt_pos c' kk = 1" and "i < 2 * c"
      have idx_nz: "Suc i  0" by simp
      show "mt_tape cM kk (Suc i)  le_tm M"
        using valid_reach_LE_only_pos0_mttm
                [OF vM lu w_sub reach_cM idx_nz le_neq_bl[symmetric]] .
    next
      fix kk :: nat and i :: nat
      assume "mt_pos c' kk = 0" and "i < c"
      have idx_nz: "Suc i  0" by simp
      show "mt_tape cM kk (Suc i)  le_tm M"
        using valid_reach_LE_only_pos0_mttm
                [OF vM lu w_sub reach_cM idx_nz le_neq_bl[symmetric]] .
    qed
    ― ‹Substep G: invoke forward_stage_general› on the
        first chunk cM →k_chunk cM_k› to obtain an
        M'-witness c8› of length 8 satisfying the invariants
        needed to recurse on the remaining trace.  All twelve
        hypotheses are now in hand: vM›, sim› (from
        less.prems›), cM› in Q› + non-halt (substep A),
        buf_gamma› + le_anchor› (from less.prems›),
        k_chunk_le_c› (substep B), chunk_trace› (substep
        C), end_or_halt› (substep E), le_neq_bl› (outer
        assume), no_le_per_tape› (substep F).  Uses
        obtain ... by (rule ...)› as the obtains›-elim
        pattern (automation diverges on obtains› rules
        with multiple output conjuncts).›
    have k_chunk_le_card: "k_chunk  card (UNIV :: 'c set)"
      using k_chunk_le_c unfolding c_def .
    have end_or_halt_card:
        "k_chunk = card (UNIV :: 'c set)
           mt_state cM_k  {t_tm M, r_tm M}"
      using end_or_halt unfolding c_def .
    have no_le_per_tape_card:
        "kk. (mt_pos c' kk  2
                 (i. i < 3 * card (UNIV :: 'c set)
                           mt_tape cM kk
                                ((mt_pos c' kk - 2) * card (UNIV :: 'c set) + 1 + i)
                               le_tm M))
              (mt_pos c' kk = 1
                   (i. i < 2 * card (UNIV :: 'c set)
                             mt_tape cM kk (Suc i)  le_tm M))
              (mt_pos c' kk = 0
                   (i. i < card (UNIV :: 'c set)
                             mt_tape cM kk (Suc i)  le_tm M))"
      using no_le_per_tape unfolding c_def .
    obtain c8 where
        chain8: "(c', c8)  mttm_step (alphabet_enlarge_delta M) ^^ 8"
      and sim_c8: "ae_simulates M cM_k c8"
      and buf_gamma_c8: "ae_buffer_in_gamma_block M c8"
      and le_anchor_c8: "kk<k_tm M. mt_tape c8 kk 0 = LE_block (le_tm M)"
      by (rule ae_simulates_forward_stage_general
                 [OF vM lu less.prems(4) cM_in_Q cM_neq_t cM_neq_r
                     less.prems(5) k_chunk_le_card chunk_trace
                     end_or_halt_card less.prems(6) le_neq_bl
                     no_le_per_tape_card])
    ― ‹Substep H: extend the substrate-reachability of cM›
        to cM_k›.  Composes reach_cM› (an rtrancl›
        certificate) with chunk_trace› (a relpow›
        certificate of length k_chunk›) by lifting the
        relpow› to rtrancl› via relpow_imp_rtrancl›,
        then composing via rtrancl_trans›.  Needed because
        the IH recursion requires the substrate-reachability of
        the recursion's starting M-config (here, cM_k›).›
    have chunk_in_rtrancl: "(cM, cM_k)  (mttm_step (delta_tm M))*"
      using chunk_trace by (rule relpow_imp_rtrancl)
    have reach_cM_k: "(init_config_mttm M w, cM_k)
                          (mttm_step (delta_tm M))*"
      using reach_cM chunk_in_rtrancl by (rule rtrancl_trans)
    ― ‹Substep I: apply less.IH› for the remaining trace
        cM_k →(n - k_chunk) cM_final›.  Recursion is on
        n - k_chunk < n› (which holds because
        k_chunk ≥ 1› and n ≥ 1›); the re-quantified
        hypotheses are reach_cM_k› (substep H),
        rest_after_chunk› (substep C),
        less.prems(3)› (accept), sim_c8›, buf_gamma_c8›,
        le_anchor_c8› (substep G).  Yields the recursion-arm
        witness (m_rec, c'')›: an M'-path of length m_rec›
        from c8› ending in canonical halt, with m_rec›
        bounded by 8 ⋅ ⌈(n - k_chunk) / c⌉›.›
    have n_minus_lt_n: "n - k_chunk < n"
      using k_chunk_pos Suc by linarith
    obtain m_rec c'' where
        bound_rec: "m_rec  8 * ((n - k_chunk + card (UNIV :: 'c set) - 1)
                                   div card (UNIV :: 'c set))"
      and chain_rec: "(c8, c'')  (mttm_step (alphabet_enlarge_delta M))^^m_rec"
      and state_c'': "mt_state c'' = (t_tm M, init_stage (le_tm M))"
      using less.IH[OF n_minus_lt_n reach_cM_k rest_after_chunk
                       less.prems(3) sim_c8 buf_gamma_c8 le_anchor_c8]
      by blast
    ― ‹Substep J: compose the 8-step forward chunk chain8›
        with the recursion-arm chain_rec› via relpow_add›:
        rel ^^ 8 O rel ^^ m_rec = rel ^^ (8 + m_rec)›.›
    have chain_compose:
        "(c', c'')  (mttm_step (alphabet_enlarge_delta M))^^(8 + m_rec)"
      using chain8 chain_rec by (auto simp: relpow_add)
    ― ‹Substep K: arithmetic bound 8 + m_rec ≤ 8 ⋅ ⌈n/c⌉›.
        Case-split mirroring substep E's:
          - k_chunk = n›: n - k_chunk = 0› so m_rec = 0›
            (IH base case yields zero-bound on a zero-length
            trace); and n ≥ 1› gives ⌈n/c⌉ ≥ 1›, so the
            target 8 ≤ 8 ⋅ 1› holds.
          - k_chunk \<ne> n›: substep E forces k_chunk = c›
            (and c < n›); the IH bound becomes
            m_rec ≤ 8 ⋅ ⌈(n-1)/c⌉›, and the identity
            ⌈n/c⌉ = ⌈(n-1)/c⌉ + 1› (which holds for
            n ≥ 1, c ≥ 1›) gives the target with equality.›
    have n_pos: "0 < n" using Suc by simp
    have bound_compose:
        "8 + m_rec
           8 * ((n + card (UNIV :: 'c set) - 1)
                    div card (UNIV :: 'c set))"
    proof (cases "k_chunk = n")
      case True
      have m_rec_zero: "m_rec = 0"
      proof -
        have "n - k_chunk = 0" using True by simp
        hence "(n - k_chunk + card (UNIV :: 'c set) - 1)
                  div card (UNIV :: 'c set) = 0"
          using c_pos[unfolded c_def] by simp
        thus ?thesis using bound_rec by simp
      qed
      have one_le_ceil:
          "1  (n + card (UNIV :: 'c set) - 1)
                  div card (UNIV :: 'c set)"
      proof -
        have "card (UNIV :: 'c set)  n + card (UNIV :: 'c set) - 1"
          using n_pos by simp
        hence "card (UNIV :: 'c set) div card (UNIV :: 'c set)
                 (n + card (UNIV :: 'c set) - 1)
                    div card (UNIV :: 'c set)"
          using div_le_mono by blast
        thus ?thesis using c_pos[unfolded c_def] by simp
      qed
      show ?thesis using m_rec_zero one_le_ceil by simp
    next
      case False
      have k_chunk_eq_c: "k_chunk = c"
      proof -
        have "k_chunk < n" using k_chunk_le_n False by linarith
        hence "min n c < n" unfolding k_chunk_def by simp
        hence "c < n" by linarith
        hence "min n c = c" by simp
        thus ?thesis unfolding k_chunk_def by simp
      qed
      have n_gt_c: "c < n"
        using False k_chunk_le_n k_chunk_eq_c by linarith
      have n_minus_eq: "n - k_chunk + c - 1 = n - 1"
        using k_chunk_eq_c n_gt_c by simp
      have rec_bound:
          "m_rec  8 * ((n - 1) div card (UNIV :: 'c set))"
        using bound_rec n_minus_eq unfolding c_def by simp
      have ceil_step:
          "(n + card (UNIV :: 'c set) - 1)
              div card (UNIV :: 'c set)
            = (n - 1) div card (UNIV :: 'c set) + 1"
      proof -
        have c_nz: "card (UNIV :: 'c set)  0"
          using c_pos unfolding c_def by simp
        have sum_eq: "n + card (UNIV :: 'c set) - 1
                       = (n - 1) + card (UNIV :: 'c set)"
          using n_pos by simp
        have div_step:
            "((n - 1) + card (UNIV :: 'c set))
                div card (UNIV :: 'c set)
              = (n - 1) div card (UNIV :: 'c set) + 1"
          using div_add_self2[OF c_nz] .
        show ?thesis using sum_eq div_step by simp
      qed
      have "8 + m_rec
               8 + 8 * ((n - 1) div card (UNIV :: 'c set))"
        using rec_bound by simp
      also have " = 8 * ((n - 1) div card (UNIV :: 'c set) + 1)"
        by simp
      also have " = 8 * ((n + card (UNIV :: 'c set) - 1)
                            div card (UNIV :: 'c set))"
        using ceil_step by simp
      finally show ?thesis .
    qed
    ― ‹Final assembly: witnesses (8 + m_rec, c'')› satisfy
        the bound (8 + m_rec) ≤ 8 ⋅ ⌈n/c⌉›, the chain
        (c', c'') ∈ alphabet_enlarge_delta^^(8 + m_rec)›, and
        the canonical halt state (t_tm M, init_stage le_M)›.›
    show ?thesis
      using bound_compose chain_compose state_c'' by blast
  qed
qed

text ‹Simulation-phase step count under weak acceptance.  If
  M› accepts u› within time T (length u)› (an accepting
  M›-path of length at most T (length u)› from
  init_config_mttm M u› to a config in state t_tm M›),
  then from any simulation-paired SS1 config c'› there is an
  accepting M'›-path of length at most 8 * ⌈T(length u) / c⌉›
  ending at (t_tm M, init_stage (le_tm M))›.

  Under the weak time-bounded acceptance convention
  (accepts_in_time_mttm›).  Hypothesis
  accepts_in_time_mttm M u (T (length u))› replaces the
  universal-path-bound upperb_time_mttm M T›; conclusion drops
  the r_tm›-arm (under weak acceptance, "reject" just means
  "no accepting path"; no canonical r_tm› config is tracked
  explicitly).  Thin
  wrapper around ae_simulation_phase_chunked›: unpacks
  the weak-acceptance witness, lifts the tight bound
  (n0 + c - 1) div c› to the T (length u)› bound
  via monotonicity of division, and adapts to the
  obtains›-form.›

lemma ae_simulation_phase_step_count:
  fixes M :: "('q, 'a) mttm"
    and T :: "nat  nat"
    and u :: "'a list"
    and c' :: "('c :: enum  'a,
                'q × ('a, 'c) ae_stage) mt_config"
  assumes vM:         "valid_mttm M"
      and lu:         "le_unique M"
      and m_accepts:  "accepts_in_time_mttm M u (T (length u))"
      and u_sub:      "set u  Sigma_tm M"
      and sim:        "ae_simulates M (init_config_mttm M u) c'"
      and buf_gamma_c': "ae_buffer_in_gamma_block M c'"
      and le_anchor_c': "kk<k_tm M. mt_tape c' kk 0 = LE_block (le_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 n_steps :: nat and c'' where
      "n_steps  8 * ((T (length u) + card (UNIV :: 'c set) - 1)
                       div card (UNIV :: 'c set))"
    and "(c', c'')  mttm_step (alphabet_enlarge_delta M) ^^ n_steps"
    and "mt_state c'' = (t_tm M, init_stage (le_tm M))"
proof -
  ― ‹Step 1: unpack the weak-acceptance witness — the specific
      accepting M›-path of length n0 ≤ T (length u)›
      from init_config_mttm M u› to a config in state t_tm M›.›
  from m_accepts obtain n0 cM_n0 where
      n0_bd:  "n0  T (length u)"
    and n0_run: "(init_config_mttm M u, cM_n0)
                     mttm_step (delta_tm M) ^^ n0"
    and n0_acc: "mt_state cM_n0 = t_tm M"
    unfolding accepts_in_time_mttm_def by blast
  ― ‹Step 2: invoke the chunked-induction helper.  Reachability
      of the starting M-config (init_config_mttm M u›) from
      itself is reflexive.  The helper returns an M'-witness path
      with the tight bound 8 ⋅ ⌈n0/c⌉›; the wrapper relaxes
      this to 8 ⋅ ⌈T(|u|)/c⌉› via monotonicity of
      (_ + c - 1) div c› in the dividend.›
  have init_reach:
      "(init_config_mttm M u, init_config_mttm M u)
           (mttm_step (delta_tm M))*"
    by simp
  obtain n_steps c'' where
      tight_bound: "n_steps  8 * ((n0 + card (UNIV :: 'c set) - 1)
                                       div card (UNIV :: 'c set))"
    and run:   "(c', c'')  mttm_step (alphabet_enlarge_delta M) ^^ n_steps"
    and halt:  "mt_state c'' = (t_tm M, init_stage (le_tm M))"
    using ae_simulation_phase_chunked[OF vM lu u_sub le_neq_bl s_neq_t s_neq_r
                                          init_reach n0_run n0_acc sim
                                          buf_gamma_c' le_anchor_c']
    by blast
  ― ‹Step 3: arithmetic — relax the tight n0›-bound to the
      loose T(|u|)›-bound using n0 ≤ T (length u)› and
      monotonicity of div› on the dividend.›
  have div_mono:
      "(n0 + card (UNIV :: 'c set) - 1) div card (UNIV :: 'c set)
          (T (length u) + card (UNIV :: 'c set) - 1)
              div card (UNIV :: 'c set)"
    using n0_bd by (intro div_le_mono add_le_mono) auto
  have loose_bound:
      "n_steps  8 * ((T (length u) + card (UNIV :: 'c set) - 1)
                       div card (UNIV :: 'c set))"
    using tight_bound div_mono by linarith
  show ?thesis
  proof (rule that)
    show "n_steps  8 * ((T (length u) + card (UNIV :: 'c set) - 1)
                            div card (UNIV :: 'c set))"
      using loose_bound .
    show "(c', c'')  mttm_step (alphabet_enlarge_delta M) ^^ n_steps"
      using run .
    show "mt_state c'' = (t_tm M, init_stage (le_tm M))"
      using halt .
  qed
qed

end